标 题: 【原创】shellcode汇编之采用API函数
作 者: jgaoabc
时 间: 2010-11-19
内容比较肤浅,大牛莫笑。
按照shellcode代码的方式用汇编语言编写程序的优点在于它的可移植性,因为它没有重定位,没有输入表。如果把它写成一个子程序,可以在任意用得着的程序中粘贴调用它。
重定位可以采用自定位的方式来解决,同样输入表函数也可以采用搜索的方式来取得。
要取得输入表函数的内存指针,首先须取得kernel32.dll基址,这个不难,看雪论坛是我们的老师,看这个文章《Win 7下定位kernel32.dll基址及shellcode编写》http://bbs.pediy.com/showthread.php?t=122260。其次,采用搜
索取得各DLL的API函数的地址,网络上也有很多办法,我从Poison Ivy 2.3.2中找到了一个好办法,附带说下Poison Ivy 2.3.2的服务端,它就是按照shellcode格式编写的,它的代码是可移植的,但是它在WINDOWS 7下却不能运行,因
为它取得kernel32.dll基址的方法不适用于WINDOWS 7,如果把它换成看雪论坛的方法(也就是下面的代码),就可以在WINDOWS 7运行了。
取得kernel32.dll基址的子程序汇编代码:(二进制代码请看附件)
00401000 KrnlB> 51 push ecx
00401001 56 push esi
00401002 57 push edi
00401003 33C9 xor ecx,ecx
00401005 64:8B71 30 mov esi,dword ptr fs:[ecx+30]
00401009 8B76 0C mov esi,dword ptr ds:[esi+C]
0040100C 8B76 1C mov esi,dword ptr ds:[esi+1C]
0040100F 8B46 08 mov eax,dword ptr ds:[esi+8]
00401012 8B7E 20 mov edi,dword ptr ds:[esi+20]
00401015 8B36 mov esi,dword ptr ds:[esi]
00401017 66:394F 18 cmp word ptr ds:[edi+18],cx
0040101B ^ 75 F2 jnz short KrnlBase.0040100F
0040101D 5F pop edi
0040101E 5E pop esi
0040101F 59 pop ecx
00401020 C3 retn
搜索API函数的子程序汇编代码:
00401021 55 push ebp
00401022 8BEC mov ebp,esp
00401024 83C4 EC add esp,-14
00401027 56 push esi
00401028 53 push ebx
00401029 57 push edi
0040102A 52 push edx
0040102B 51 push ecx
0040102C 8B45 10 mov eax,dword ptr ss:[ebp+10]
0040102F 33D2 xor edx,edx
00401031 92 xchg eax,edx
00401032 BE 3C000000 mov esi,3C
00401037 0375 0C add esi,dword ptr ss:[ebp+C]
0040103A 8B06 mov eax,dword ptr ds:[esi]
0040103C 0345 0C add eax,dword ptr ss:[ebp+C]
0040103F 8B70 78 mov esi,dword ptr ds:[eax+78]
00401042 83C6 18 add esi,18
00401045 0375 0C add esi,dword ptr ss:[ebp+C]
00401048 8B06 mov eax,dword ptr ds:[esi]
0040104A 8945 EC mov dword ptr ss:[ebp-14],eax
0040104D 83C6 04 add esi,4
00401050 8D7D F8 lea edi,dword ptr ss:[ebp-8]
00401053 AD lods dword ptr ds:[esi]
00401054 0345 0C add eax,dword ptr ss:[ebp+C]
00401057 AB stos dword ptr es:[edi]
00401058 8945 F8 mov dword ptr ss:[ebp-8],eax
0040105B AD lods dword ptr ds:[esi]
0040105C 0345 0C add eax,dword ptr ss:[ebp+C]
0040105F 50 push eax
00401060 AB stos dword ptr es:[edi]
00401061 8945 F4 mov dword ptr ss:[ebp-C],eax
00401064 8B06 mov eax,dword ptr ds:[esi]
00401066 0345 0C add eax,dword ptr ss:[ebp+C]
00401069 8945 F0 mov dword ptr ss:[ebp-10],eax
0040106C 5E pop esi
0040106D C745 FC 00000000 mov dword ptr ss:[ebp-4],0
00401074 56 push esi
00401075 8B06 mov eax,dword ptr ds:[esi]
00401077 0345 0C add eax,dword ptr ss:[ebp+C]
0040107A 97 xchg eax,edi ; 这里下断,数据窗口查看eax的值,然后在数据窗口粘贴要取得的API函数字符的二进制
0040107B 8BDF mov ebx,edi
0040107D 57 push edi
0040107E 32C0 xor al,al
00401080 AE scas byte ptr es:[edi]
00401081 ^ 75 FD jnz short KrnlBase.00401080
00401083 5E pop esi
00401084 2BFB sub edi,ebx
00401086 52 push edx
00401087 FC cld
00401088 33C9 xor ecx,ecx
0040108A 49 dec ecx
0040108B 8BD1 mov edx,ecx
0040108D 33C0 xor eax,eax
0040108F 33DB xor ebx,ebx
00401091 AC lods byte ptr ds:[esi]
00401092 32C1 xor al,cl
00401094 8ACD mov cl,ch
00401096 8AEA mov ch,dl
00401098 8AD6 mov dl,dh
0040109A B6 08 mov dh,8
0040109C 66:D1EB shr bx,1
0040109F 66:D1D8 rcr ax,1
004010A2 73 09 jnb short KrnlBase.004010AD
004010A4 66:35 2083 xor ax,8320
004010A8 66:81F3 B8ED xor bx,0EDB8
004010AD FECE dec dh
004010AF ^ 75 EB jnz short KrnlBase.0040109C
004010B1 33C8 xor ecx,eax
004010B3 33D3 xor edx,ebx
004010B5 4F dec edi
004010B6 ^ 75 D5 jnz short KrnlBase.0040108D
004010B8 F7D2 not edx
004010BA F7D1 not ecx
004010BC 8BC2 mov eax,edx
004010BE C1C0 10 rol eax,10
004010C1 66:8BC1 mov ax,cx
004010C4 5A pop edx
004010C5 3BD0 cmp edx,eax ; eax中的值是DLL函数的输出表各个函数的特征值,edx是指定的特征值。
004010C7 74 0A je short KrnlBase.004010D3
004010C9 5E pop esi
004010CA 83C6 04 add esi,4
004010CD 8345 FC 01 add dword ptr ss:[ebp-4],1
004010D1 ^ EB A1 jmp short KrnlBase.00401074
004010D3 5E pop esi
004010D4 8B45 FC mov eax,dword ptr ss:[ebp-4]
004010D7 D1E0 shl eax,1
004010D9 0345 F0 add eax,dword ptr ss:[ebp-10]
004010DC 33F6 xor esi,esi
004010DE 96 xchg eax,esi
004010DF 66:8B06 mov ax,word ptr ds:[esi]
004010E2 66:C1E0 02 shl ax,2
004010E6 0345 F8 add eax,dword ptr ss:[ebp-8]
004010E9 96 xchg eax,esi
004010EA 8B06 mov eax,dword ptr ds:[esi]
004010EC 0345 0C add eax,dword ptr ss:[ebp+C]
004010EF 59 pop ecx
004010F0 5A pop edx
004010F1 5F pop edi
004010F2 5B pop ebx
004010F3 5E pop esi
004010F4 C9 leave
004010F5 C2 0C00 retn 0C
运用上面的子程序取得API函数的格式如下:
00401020 68 0736F319 push 19F33607 API函数特征值
00401025 FF75 FC push dword ptr ss:[ebp-4] API函数所属的DLL的基址
00401028 6A 00 push 0
0040102A E8 B2120000 call 00401021 搜索API函数的子程序
运行后eax就是API函数的内存指针
下面就我编写的一个反调试实例EnableWindow(在看雪论坛查反调试技术实例)做下说明:
这个程序用到了二个函数,user32.dll有GetForegroundWindow和EnableWindow,当然要取得user32.dll的基址,须调用kernel32.dll的LoadLibraryA。
004010F8 55 push ebp
004010F9 8BEC mov ebp,esp
004010FB 83EC 20 sub esp,20
004010FE 53 push ebx
004010FF 56 push esi
00401100 57 push edi
00401101 E8 FAFEFFFF call KrnlBase.00401000 ; 取得kernel32.dll基址
00401106 8945 FC mov dword ptr ss:[ebp-4],eax
00401109 68 ADD13441 push 4134D1AD ; LoadLibraryA的特征值
0040110E FF75 FC push dword ptr ss:[ebp-4] ; kernel32.dll基址
00401111 6A 00 push 0
00401113 E8 09FFFFFF call KrnlBase.00401021 ; 搜索API函数的子程序
00401118 8945 F8 mov dword ptr ss:[ebp-8],eax
0040111B E8 07000000 call KrnlBase.00401127 ; 自定位user32的地址
00401120 75 73 jnz short KrnlBase.00401195 ; user32
00401122 65:72 33 jb short KrnlBase.00401158
00401125 3200 xor al,byte ptr ds:[eax]
00401127 FF55 F8 call dword ptr ss:[ebp-8] ; 调用LoadLibraryA
0040112A 8BF0 mov esi,eax
0040112C 68 3F235577 push 7755233F ; GetForegroundWindow的特征值
00401131 56 push esi
00401132 6A 00 push 0
00401134 E8 E8FEFFFF call KrnlBase.00401021
00401139 8945 F4 mov dword ptr ss:[ebp-C],eax
0040113C 68 09D99B70 push 709BD909 ; EnableWindow的特征值
00401141 56 push esi
00401142 6A 00 push 0
00401144 E8 D8FEFFFF call KrnlBase.00401021
00401149 8945 F0 mov dword ptr ss:[ebp-10],eax
0040114C FF55 F4 call dword ptr ss:[ebp-C] ; user32.GetForegroundWindow
0040114F 8BF8 mov edi,eax
00401151 6A 00 push 0 ; 禁止窗口
00401153 57 push edi
00401154 FF55 F0 call dword ptr ss:[ebp-10] ; user32.EnableWindow
00401157 6A 01 push 1 ; 允许窗口
00401159 57 push edi
0040115A FF55 F0 call dword ptr ss:[ebp-10] ; user32.EnableWindow
0040115D 5F pop edi
0040115E 5E pop esi
0040115F 5B pop ebx
00401160 83C4 20 add esp,20
00401163 5D pop ebp
00401164 C3 retn
注意:运行禁止窗口的00401154之后,整个OD将被禁止,你只能在任务管理器关闭OD。把禁止窗口和允许窗口一起运行比如在40115D设断就可以避免。
本程序在2003、XP和WINDOWS 7运行通过。
函数特征值取得的方法:
先把API函数字符换成二进制代码,如EnableWindow,先把它换成二进制456E61626C6557696E646F7700,注意后面有00结束,这项工作可以在C32ASM中进行,然后在0040107A下断,在数据窗口跟踪eax的值,并且在数据窗口把API函数
的二进制字符粘贴进去,然后再在004010C5下断,eax里的值就是API函数的特征值。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!