Starting
环境:<span>Windows</span> <span>XP</span><br><span>VC</span>++ 6<span>.0</span><br>
此方法只适用于测试或者学习,无法动态执行shellcode。也就是说shellcode只能在XP上使用,因为从win7开始有了aslr
ASLR说明:https://blog.morphisec.com/aslr-what-it-is-and-what-it-isnt/
弹框测试:
<span>#<span>include</span><span><windows.h></span></span><br><span><span>int</span> <span>main</span><span>(<span>int</span> argc,<span>char</span>** argv)</span></span>{<br> MessageBox(<span>NULL</span>,<span>"You are hacked by Migraine!"</span>,<span>"Pwned"</span>,MB_OK);<br>}<br>
Alt+8调出反汇编模式可以观察是如何实现调用win API的
通过参阅文章发现不能直接提取机器码,必须用汇编在写一遍。然后在提取字节码
通过参阅文章明白汇编执行shellcode是如何执行的
<span>//转自安全客文章</span><br><span>#<span>include</span><span><windows.h></span></span><br><span><span>void</span> <span>main</span><span>()</span><br></span>{<br> LoadLibrary(<span>"user32.dll"</span>);<span>//Load DLL</span><br> __asm<br> { <br> push <span>0x00656e</span>;ne<br> push <span>0x69617267</span>;grai<br> push <span>0x694d2079</span>;y Mi<br> push <span>0x62206565</span>;ed b<br> push <span>0x6b636168</span>;hack<br> push <span>0x20657261</span>;Are<br> push <span>0x20756F59</span>;You<br> mov ebx,esp<br> push <span>0x0</span><br> push <span>0x656e6961</span>;aine<br> push <span>0x7267694d</span>;Migr<br> mov ecx,esp<br><br><br> <span>//int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption,UINT uType );</span><br> xor eax,eax<br> push eax<span>//uTyoe->0</span><br> push ecx<span>//lpCaption->Migraine</span><br> push ebx<span>//lpText->You are hacked by Migraine</span><br> push eax<span>//hWnd->0</span><br> mov esi,<span>0x77D3ADD7</span><span>//User32.dll->MessageBoxA</span><br> call esi<br><br><br> }<br>}<br>
- 将需要用到的字符串转成十六进制,由于是X86,一次可最多存放8个字节
- 将字符串转换的十六进制入栈
- push 0x0后然后重复将需要的东西入栈,在次保存到另外个寄存器
- 然后从右到左设置win API的值(注意:从右到左)
- 最后将windows API的地址给esi
- call 将当前执行指令地址入栈,然后无条件转移到由标签指示的指令
通过OD给对应的API下断点,可以取得地址
(注:每个系统的地址都有差异)
Examlpe:
然后使用C内嵌asm,调试提取机器码
整个asm范围的机器码提取出来:
<span>"\x68\x6E\x65\x00\x00\x68\x67\x72\x61\x69\x68\x79\x20\x4D\x69\x68\x65\x65\x20\x62"</span><br><span>"\x68\x68\x61\x63\x6B\x68\x61\x72\x65\x20\x68\x61\x62\x63\x00\x8B\xDC\x6A\x00\x68"</span><br><span>"\x61\x69\x6E\x65\x68\x4D\x69\x67\x72\x8B\xCC\x33\xC0\x50\x68\x61\x69\x6E\x65\x68"</span><br><span>"\x4D\x69\x67\x72\x8B\xCC\x33\xC0\x50\x51\x53\x50\xBE\xEA\x07\xD5\x77\xFF\xD6"</span><br>
执行即可:
用WinExec弹个calc
<span>//WinExec address-7C86250D</span><br><span>//ExitProcess address-7C81CB12</span><br><span>#<span>include</span><span><windows.h></span></span><br><span><span>int</span> <span>main</span><span>()</span><br></span>{<br> LoadLibrary(<span>"kernel32.dll"</span>);<br> __asm<br> {<br> push <span>0x636C6163</span>;calc<br> mov eax,esp<br> push <span>0x0</span><br> push <span>0x5</span><br> mov ebx,esp<br><br><br> push ebx<br> push eax<br> mov esi,<span>0x7C86250D</span><br> call esi<br> xor ecx,ecx<br> mov esi,<span>0x7C81CB12</span><br> call esi<br> }<br> <span>return</span> <span>0</span>;<br>}<br>
shellcode为
<span>"\x68\x63\x61\x6C\x63\x8B\xC4\x6A\x05\x8B\xDC\x53\x50\xBE\x0D\x25\x86\x7C"</span><br><span>"\xFF\xD6\x33\xC9\xBE\x12\xCB\x81\x7C\xFF\xD6"</span><br>
注意:如果你不知道calc变成十六进制怎么整,汇编整一个就好