-
Windows Shellcode学习笔记——通过VirtualProtect绕过DEP
0x00 前言 在掌握了栈溢出的基本原理和利用方法后,接下来就要研究如何绕过Windows系统对栈溢出利用的重重防护,所以测试环境也从xp转到了Win7(相比xp,Win7的防护更全面)。本文将要介绍经典的DEP绕过方法——通过VirtualProtect绕过DEP 0x01 简介 本文将要介绍以下内容: VS2012的编译配置 利用Immunity Debugger的mona插件自动获取ROP链 对ROP链的分析调试 调用VirtualProtect函数时的Bug及修复 0x02 相关概念 DEP: 溢出攻击的根源在于计算机对数据和代码没有明确区分,如果将代码放置于数据段,那么系统就会去执行 为了弥补这一缺陷,微软从XP SP2开始支持数据执行保护(Data Exection Prevention) DEP保护原理: 数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,而有了DEP,此时CPU会抛出异常,而不是去执行指令 DEP四种工作状态: Optin Optout AlwaysOn AlwaysOff DEP绕过原理: 如果函数返回地址并不直接指向数据段,而是指向一个已存在的系统函数的入口地址,由于系统函数所在的页面权限是可执行的,这样就不会触发DEP 也就是说,可以在代码区找到替代指令实现shellcode的功能 但是可供利用的替代指令往往有限,无法完整的实现shellcode的功能 于是产生了一个折中方法:通过替代指令关闭DEP,再转入执行shellcode 内存页: x86系统一个内存页的大小为4kb,即0x00001000,4096 ROP: 面向返回的编程(Return-oriented Programming) VirtualProtect: BOOL VirtualProtect{ LPVOID lpAddress, DWORD dwsize, DWORD flNewProtect, PDWORD lpflOldProtect } lpAddress:内存起始地址 dwsize:内存区域大小...
-
Windows Shellcode学习笔记——栈溢出中对jmp esp的利用与优化
0x00 前言 在《Windows Shellcode学习笔记——shellcode在栈溢出中的利用与优化》中对栈溢出的利用做了介绍。通过将返回地址覆盖为shellcode在内存中的起始地址,实现对栈溢出的利用 但是shellcode在内存中的起始地址往往不固定,导致漏洞利用不一定成功,本文将通过jmp esp的方式来解决这个问题 0x01 简介 函数代码在栈中保存顺序(直观理解,已省略其他细节): buffer 前栈帧EBP 返回地址 ESP ESP寄存器总是指向返回地址的下一地址 如果用jmp esp覆盖返回地址,那么在函数返回后会执行jmp esp,跳到esp,也就是返回地址的下一地址开始执行 因此,将shellcode放于返回地址之后,并将返回地址覆盖为jmp esp,就可以避免shellcode在内存中产生的移位问题 本文将要介绍使用jmp esp的具体细节,并分享如何优化我们自己生成的弹框实例shellcode,实现jmp esp利用,编写程序自动实现,解决shellcode在内存中的起始地址不固定的问题。 弹框实例shellcode下载地址: https://github.com/3gstudent/Shellcode-Generater/blob/master/shellcode.bin 0x01 jmp esp 获得jmp esp的机器码: 可通过搜索各个进程空间来获取,具体原理可参考《0day安全:软件漏洞分析技术》3.2.2节 为便于理解和测试,直接引用《0day安全:软件漏洞分析技术》3.2.2节中的代码,代码如下: #include <stdio.h> #include <windows.h> #define DLL_NAME "user32.dll" int main() { BYTE *ptr; int position,address; HINSTANCE handle; BOOL done_flag=FALSE; handle=LoadLibrary(DLL_NAME);...
-
Windows Shellcode学习笔记——shellcode在栈溢出中的利用与优化
0x00 前言 在《Windows Shellcode学习笔记——shellcode的提取与测试》中介绍了如何对shellcode作初步优化,动态获取Windows API地址并调用,并通过程序实现自动提取机器码作为shellcode并保存到文件中。 弹框实例shellcode的bin文件已上传至github,地址如下: https://github.com/3gstudent/Shellcode-Generater/blob/master/shellcode.bin 注: shellcode.bin由getshellcode.cpp生成 getshellcode.cpp地址如下: https://github.com/3gstudent/Shellcode-Generater/blob/master/getshellcode.cpp 接下来,要研究shellcode在具体环境中的使用和优化技巧 0x01 简介 先从最入门的缓冲区溢出开始 本文将要结合《0day安全:软件漏洞分析技术》中的“栈溢出原理与实践”章节,以其中的栈溢出代码作样本,优化我们自己生成的弹框实例shellcode,实现在栈溢出中的初步利用。 0x02 相关概念 栈区: 用于动态地存储函数之间的调用关系,以保证被调用函数在返回时恢复到母函数中继续执行 特殊寄存器: ESP:栈指针寄存器(extended stack pointer),指向栈顶 EBP:基址指针寄存器(extended base pointer),指向栈底 EIP:指令寄存器(extended instruction pointer),指向下一条等待执行的指令地址 函数代码在栈中保存顺序(直观理解,已省略其他细节): buffer 前栈帧EBP 返回地址 ESP 函数栈溢出原理(直观理解,已省略其他细节): 正常情况下函数在返回过程中,最后会执行返回地址中保存的内容,通常是跳到下一条指令的地址 如果buffer长度过长,长到覆盖了返回地址的值,那么函数在返回时,就会执行被覆盖的内容 如果将shellcode保存到buffer中,覆盖的返回地址为shellcode的起始地址,那么,shellcode将得到执行,完成栈溢出的利用 0x03 栈溢出实例测试 样本代码如下: #include <stdio.h> #include <windows.h> #define PASSWORD "1234567" int...
-
Windows Shellcode学习笔记——shellcode的提取与测试
0x00 前言 之前在《Windows Shellcode学习笔记——通过VisualStudio生成shellcode》介绍了使用C++编写(不使用内联汇编),实现动态获取API地址并调用,对其反汇编提取shellcode的方法,并开源了测试代码。 接下来在对shellcode进行提取的过程中,发现了当时开源代码的一些bug,所以本文着重解决测试代码的bug,并介绍使用C++开发shellcode需要考虑的一些问题。 存在bug的测试代码下载地址: https://github.com/3gstudent/Shellcode-Generater/blob/master/shellcode.cpp 0x01 简介 简单的shellcode提取流程: 使用c++开发代码 更改VisualStudio编译配置 生成exe 在IDA下打开生成的exe,获得机器码 由于是动态获取API地址并调用,所以为了保证shellcode的兼容性,代码中不能出现固定地址,并且要尽量避免使用全局变量,如果代码中包含子函数,根据调用方式,还有注意各个函数之间的排列顺序(起始函数放于最前) 0x02 Bug修复 配置三个编译选项:release、禁用优化、禁用/GS 将代码编译,然后使用IDA提取机器码作为shellcode 在实际调试过程中,发现代码存在bug: 1、代码中应合理处理全局变量 在代码中使用全局变量 FARPROC(WINAPI* GetProcAddressAPI)(HMODULE, LPCSTR); HMODULE(WINAPI* LoadLibraryWAPI)(LPCWSTR); 在编译后会成为一个固定地址,导致shellcode无法兼容不同环境 最简单直接的方式是在shellcode中尽量避免全局变量 2、函数声明方式需要修改 修改全局变量后,以下代码需要修改: MESSAGEBOXA_INITIALIZE MeassageboxA_MyOwn = reinterpret_cast<MESSAGEBOXA_INITIALIZE>(GetProcAddressAPI(LoadLibraryWAPI(struser32), MeassageboxA_api)); MeassageboxA_MyOwn(NULL, NULL, NULL, 0); 需要全部换成typedef的函数声明方式 3、函数调用顺序 如果使用以下方式加载shellcode: (*(int(*)()) sc)(); 起始函数的定义应该位于这段shellcode的最前面(和函数声明的顺序无关) 注: shellcode如果包含子函数,应该保证各个函数放在一段连续的地址中,并且起始函数置于最前面,这样在提取机器码后,可以直接加载起始函数执行shellcode 综上,给出新的完整代码: #include...
-
32位程序对64位进程的远程注入实现
0x00 前言 要对指定进程进行远程注入,通常使用Windows提供的API CreateRemoteThread创建一个远程线程,进而注入dll或是执行shellcode。 在64位系统下,该方法需要特别注意,注入的目标进程要同程序的结构保持一致,即32位程序只能对32进程作注入,64位程序只能对64位进程作注入 32位程序对64位程序进行注入时会失败(32位和64位的结构不同) 然而,在某些特殊的环境下,无法提前预知目标进程的结构,准备两个不同版本的程序又不现实 所以只能重新思考这个问题: 32位程序真的无法对64位程序进行远程注入吗? 0x01 简介 我在odzhan的博客里找到了解决思路,文章地址如下: https://modexp.wordpress.com/2015/11/19/dllpic-injection-on-windows-from-wow64-process/ 本文将会介绍实现思路,参考odzhan的开源工程”pi”,编写测试代码,生成32位程序,实现对64位进程calc.exe的进程注入,验证32位程序能够对64进程作注入的结论 0x02 实现思路 1、32位程序支持对64位程序的读写 参考资料: rgb/29a: http://www.vxheaven.org/lib/vrg02.html ReWolf: http://blog.rewolf.pl/blog/ https://github.com/rwfpl/rewolf-wow64ext 2、 利用CreateRemoteThread作进程注入的通用方法 进程注入流程: OpenProcess VirtualAllocEx WriteProcessMemory VirtualProtectEx CreateRemoteThread WaitForSingleObject 在具体的实现过程中,如果指定了进程名称,需要先将进程名称转换为进程ID,参考代码如下: DWORD processNameToId(LPCTSTR lpszProcessName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnapshot, &pe))...
-
Windows Shellcode学习笔记——通过VisualStudio生成shellcode
0x00 前言 shellcode是一段机器码,常用作漏洞利用中的载荷(也就是payload) 在渗透测试中,最简单高效的方式是通过metasploit生成shellcode,然而在某些环境下,需要定制开发自己的shellcode,所以需要对shellcode的开发作进一步研究 0x01 简介 编写Shellcode的基本方式有3种: 直接编写十六进制操作码 采用C或者Delphi这种高级语言编写程序,编译后,对其反汇编进而获得十六进制操作码 编写汇编程序,将该程序汇编,然后从二进制中提取十六进制操作码 本文将介绍如何通过Visual Studio编写c代码来生成shellcode,具体包含以下三部分内容: 利用vc6.0的DEBUG模式获取shellcode 测试Shellcode自动生成工具——ShellcodeCompiler 使用C++编写(不使用内联汇编),实现动态获取API地址并调用,对其反汇编可提取出shellcode 0x02 利用vc6.0的DEBUG模式获取shellcode 注: 本节参考爱无言的《挖0day》附录部分 测试系统: Windows XP 1、编写弹框测试程序并提取汇编代码 代码如下: #include "stdafx.h" #include <windows.h> int main(int argc, char* argv[]) { MessageBoxA(NULL,NULL,NULL,0); return 0; } 在MessageBoxA(NULL,NULL,NULL,0);处,按F9下断点 debug模式按F5开始调试,跳到断点 按Alt+8将当前C代码转为汇编代码,如图 00401028 mov esi,esp 0040102A push 0 0040102C push 0...
-
渗透技巧——快捷方式文件的参数隐藏技巧
0x00 前言 最近,phrozensoft在博客中介绍了关于快捷方式的利用技巧,实现了将应用程序存储在快捷方式当中,当用户打开快捷方式时,通过vbs脚本释放应用程序并运行。 我对此很感兴趣,因为快捷方式的参数默认存在长度限制,最大为260,并且我在研究jsrat的过程也遇到过这个问题(最后通过调用sct文件解决了长度限制问题) phrozensoft分享了Delphi格式的POC代码,本文将要对其进行测试,研究lnk的文件格式,开发出对应powershell实现的POC代码,简单分析该技术的利用和防御方法 phrozensoft博客地址: https://www.phrozensoft.com/2016/12/shortcuts-as-entry-points-for-malware-poc-part-2-19 0x01 简介 Delphi 是Windows平台下著名的快速应用程序开发工具 Borland公司研发 也可以在LINUX平台上开发应用,其在LINUX上的对应产品Kylix 常用版本: Borland Delphi 7 Delphi 2010 0x02 Delphi POC测试 phrozensoft博客中也分享了其他功能的poc,如生成lnk文件的python脚本,本文暂不介绍,只测试其中的Delphi POC 环境搭建: 测试系统:Win7 x86 Delphi版本:Delphi 2010 注: 使用Delphi 7会存在编译不通过的错误,提示“File not found System.sysutils.dcu” 换用Delphi 2010后,poc作细微修改编译通过 1.新建工程 打开Delphi 2010 选择File-New-Other-Console Application 直接复制poc代码,提示错误,如图 2.修改poc 经测试,System.SysUtils需要更改为SysUtils 编译通过,如图 3.编译 选择Project-Build All Projects...
-
渗透测试中的msiexec
0x00 前言 在上篇研究了ClickOnce的渗透技巧,接触到了安装包的概念。关于安装包还有一个常见的是msi文件,可在命令行下通过msiexec安装,所以这次就研究一下msiexec在渗透测试中的利用技巧 0x01 简介 msiexec: 系统进程,是Windows Installer的一部分 用于安装Windows Installer安装包(MSI) 一般在运行Microsoft Update安装更新或安装部分软件的时候出现,占用内存比较大 系统自带,在命令行下使用,参数说明如下: msiexec /Option <Required Parameter> [Optional Parameter] Install Options </package | /i> <Product.msi> Installs or configures a product /a <Product.msi> Administrative install - Installs a product on the network /j<u|m> <Product.msi> [/t <Transform List>] [/g <Language ID>] Advertises...
-
渗透测试中的ClickOnce
0x00 前言 最近Casey Smith@subTee在《Mimikatz Delivery via ClickOnce with URL Parameters》中介绍了如何在ClickOnce程序中传入URL参数,实现执行mimikatz的技巧,并分享了一个POC 我对此很感兴趣,于是做了进一步的学习和研究 本文将会记录学习心得,介绍ClickOnce的使用方法,总结基于ClickOnce的攻击技巧和防御措施 博客地址: http://subt0x10.blogspot.com/2016/12/mimikatz-delivery-via-clickonce-with.html POC地址: https://gist.github.com/subTee/bd446efeacf656c67f5c17ca0787f15b 0x01 简介 ClickOnce: ClickOnce 是一种部署技术,使用该技术可创建自行更新的基于Windows的应用程序,这些应用程序可以通过最低程度的用户交互来安装和运行 使用用ClickOnce主要解决了程序部署中的几个问题: 更新应用程序的困难 使用 Microsoft Windows Installer 部署,每次应用程序更新时,用户都必须重新安装整个应用程序;使用 ClickOnce 部署,则可以自动提供更新。只有更改过的应用程序部分才会被下载,然后会从新的并行文件夹重新安装完整的、更新后的应用程序。 对用户的计算机的影响 使用 Windows Installer 部署时,应用程序通常依赖于共享组件,这便有可能发生版本冲突;而使用 ClickOnce 部署时,每个应用程序都是独立的,不会干扰其他应用程序。 安全权限 Windows Installer 部署要求管理员权限并且只允许受限制的用户安装;而 ClickOnce 部署允许非管理用户安装应用程序并仅授予应用程序所需要的那些代码访问安全权限 简单理解,ClickOnce部署的优点: 简化安装和更新应用程序的过程 可以自动更新 支持从Web更新 更安全,仅授予应用程序所必需的权限,通常为Intranet区域 详细介绍可参考如下链接: https://msdn.microsoft.com/zh-cn/cn/library/142dbbz4(v=vs.90).aspx...
-
Powershell tricks::Hide Process by kd.exe
0x00 前言 Pierre-Alexandre Braeken在SecTor2016上做了一个很棒的演讲——HACK MICROSOFT BY USING MICROSOFT SIGNED BINARIES 他对自己开源的工具PowerMemory做了介绍,将powershell同使用微软签名的程序相结合,可以绕过Device Guard和杀毒软件的拦截 演讲视频地址: https://sector.ca/sessions/hack-microsoft-by-using-microsoft-signed-binaries/ PowerMemory项目地址: https://github.com/giMini/PowerMemory/ 0x01 简介 PowerMemory内包含的脚本很多,其中一个比较有趣的脚本是Hide-Me.ps1,通过借助kb.exe来实现对进程的隐藏 本文将对该脚本进行测试,介绍进程隐藏的原理,修改原脚本,分析利用和防御方法。 0x02 相关概念 PCB(process control block): 进程控制块,是系统为了管理进程专门设置的一个数据结构 PCB的组织方式: 线性表方式:不论进程的状态如何,将所有的PCB连续地存放在内存的系统区。这种方式适用于系统中进程数目不多的情况 索引表方式:该方式是线性表方式的改进,系统按照进程的状态分别建立就绪索引表、阻塞索引表等 链接表方式:系统按照进程的状态将进程的PCB组成队列,从而形成就绪队列、阻塞队列、运行队列等 不同操作系统的PCB结构不同 Windows下的PCB是EPROCESS结构 进程链表是一个双向环链表 EPROCESS结构: 每个进程都有一个EPROCESS结构,里面保存着进程的各种信息和相关结构的指针 注: Windows各版本的EPROCESS结构存在差异 EPROCESS结构位于系统地址空间,所以访问这个结构需要有ring0的权限 注: Windows开启Local kernel debugging模式后,可进入ring0,使用内核态调试器 基本的内核态调试器有以下两种: kd.exe(KD) 命令行模式 常用于调试内核态的应用程序和驱动程序,调试用户态的应用程序,或者监视操作系统自身的行为等 windbg.exe(WinDbg) 界面模式 可以为Windows内核、内核态驱动程序以及用户态应用程序提供完整的源代码级调试 通过kd.exe可以查看EPROCESS结构,命令行参数如下:...