https://www.exploit-db.com/shellcodes/40245
Windows/x86 - MessageBoxA() Shellcode (242 bytes)
shellcode功能是使用MessageBox弹出一个对话框
这个shellcode 在xpsp3 与win10 上是调不通的,提示内存不能读,经过查看shellcode对应的汇编,发现作者在查找GetProcAdress这个函数式使用了错误的方法,代码片段如下:
xor ecx,ecx
mov eax,[fs:ecx+0x30] ;PEB
mov eax,[eax+0xc] ;PEB->Ldr
mov esi,[eax+0x14] ;PEB->ldr.InMemOrderModuleList
lodsd
xchg esi,eax
lodsd
mov ecx,[eax+0x10] ;kernel32 base address
xor ebx,ebx
mov ebx,[ecx+0x3c] ;DOS->elf_anew
add ebx,ecx
mov ebx,[ebx+0x78] ;DataDirectory->VirtualAddress
add ebx,ecx ;IMAGE_EXPORT_DIRECTORY
mov esi,[ebx+0x20] ;AddressOfNames
add esi,ecx
xor edx,edx
上面是通过PEB一路找到kernel32.dll的函数导出表,函数导出表结构中最后三个字段是:
函数地址表:AddressOfFunctions,存储的是导出函数的偏移
函数名称表:AddressOfNames,存储的是导出函数的名称
函数地址索引表:AddressOfNameOrdinals,存储的是函数地址表中的序号
g:
inc edx
lodsd
add eax,ecx
cmp dword [eax],'GetP'
jnz g
cmp dword [eax+4],'rocA'
jnz g
cmp dword [eax+8],'ddre'
jnz g
;执行到这里edx中存储的是函数GetProcAdress的索引,在AdressOfNameOrdinals表中同样的索引位置存储着AddressOfFunctions索引值+1。
mov esi,[ebx+0x1c] ;AddressOfFunctions
add esi,ecx
mov edx,[esi+edx*4]
;上面这一段作者直接用前面找到的索引值对AdressOfFunctions进行索引,这样做可能碰巧能获取到正确的值。修改后的代码如下:
mov eax,[ebx+24h];找到导出表中的AddressOfNameOrdinals RVA
add eax,ecx;生成VA
mov dx,word ptr[eax+edx*2];因为AddressOfNameOrdinals表示word类型,且与AddressOfNames的索引是对应的
;ax 中存放的值为GetProcAdress函数在AdressOfFunctions表中的位置
dec edx
mov eax,[ebx+1ch];找到导出表中的AddressOfFunctions的RVA
add eax,ecx;生成VA
mov edx,[eax+edx*4];找到GetProcAdress 在AdressOfFunctions 表中具体位置保存的RVA
add edx,ecx;生成VA
到这里edx中保存的就是GetProcAdress函数地址
完整的汇编代码如下,分号在汇编中表示注释:
xor ecx,ecx ; shellcod.00424B90
mov eax,dword ptr fs:[ecx+0x30]
mov eax,dword ptr ds:[eax+0xC]
mov esi,dword ptr ds:[eax+0x14]
lods dword ptr ds:[esi]
xchg eax,esi
lods dword ptr ds:[esi]
mov ecx,dword ptr ds:[eax+0x10]
xor ebx,ebx
mov ebx,dword ptr ds:[ecx+0x3C]
add ebx,ecx
mov ebx,dword ptr ds:[ebx+0x78]
add ebx,ecx
mov esi,dword ptr ds:[ebx+0x20]
add esi,ecx
xor edx,edx
;-------------------
;ecx kernel32.imagebase
;ebx kernel32.export_table.base
;-------------------
;获取GetProcAdress在导出表中的位置
getadd:
inc edx
lods dword ptr ds:[esi]
add eax,ecx
cmp dword ptr ds:[eax],0x50746547
jnz getadd
cmp dword ptr ds:[eax+0x4],0x41636F72
jnz getadd
cmp dword ptr ds:[eax+0x8],0x65726464
jnz getadd
;edx 为GetProcAdress在导出表的的索引值
;mov esi,dword ptr ds:[ebx+0x1C];这个是找到AddressOfFunctions的RVA
;add esi,ecx;生成VA
;mov edx,dword ptr ds:[esi+edx*4];使用找到的索引值在AdreessOfFuncitons 表中找RVA,但这是错误的
;add edx,ecx;生成VA
;edx 为找到的GetProcAdress的地址值,但是上面这个方法是错误的
;-------------------
;ecx kernel32.imagebase
;ebx kernel32.export_table.base
;-------------------
mov eax,[ebx+24h];找到导出表中的AddressOfNameOrdinals RVA
add eax,ecx;生成VA
mov dx,word ptr[eax+edx*2];因为AddressOfNameOrdinals表示word类型,且与AddressOfNames的索引是对应的
;ax 中存放的值为GetProcAdress函数在AdressOfFunctions表中的位置
dec edx
mov eax,[ebx+1ch];找到导出表中的AddressOfFunctions的RVA
add eax,ecx;生成VA
mov edx,[eax+edx*4];找到GetProcAdress 在AdressOfFunctions 表中具体位置保存的RVA
add edx,ecx;生成VA
;-------------------
mov esi,edx
mov edi,ecx
xor ebx,ebx
push ebx
push 0x41797261
push 0x7262694C
push 0x64616F4C
push esp
push ecx
call edx
add esp,0x10
xor ecx,ecx
push 0x42426C6C
mov byte ptr ss:[esp+0x2],cl
push 0x642E3233
push 0x72657375
push esp
call eax
add esp,0xC
xor ecx,ecx
push 0x4241786F
mov byte ptr ss:[esp+0x3],cl
push 0x42656761
push 0x7373654D
push esp
push eax
call esi
add esp,0xC
xor edx,edx
xor ecx,ecx
push edx
push 0x21216773
push 0x6D20656C
push 0x706D6153
lea edx,dword ptr ss:[esp]
push ecx
push 0x65726568
push 0x54206968
lea ecx,dword ptr ss:[esp]
xor ebx,ebx
inc ebx
push ebx
push edx
push ecx
xor ebx,ebx
push ebx
call eax
xor ecx,ecx
push 0x41737365
mov byte ptr ss:[esp+0x3],cl
push 0x636F7250
push 0x74697845
lea ecx,dword ptr ss:[esp]
push ecx
push edi
call esi
xor ecx,ecx
push ecx
call eax
nop
生成shellcode 如下:
include
include
char shellcode[]="\x33\xC9\x64\x8B\x41\x30\x3E\x8B\x40\x0C\x3E\x8B\x70\x14\xAD\x96\xAD\x3E\x8B\x48\x10\x33\xDB\x3E\x8B\x59\x3C\x03\xD9\x3E\x8B\x5B\x78\x03\xD9\x3E\x8B\x73\x20\x03\xF1\x33\xD2\x42\xAD\x03\xC1\x3E\x81\x38\x47\x65\x74\x50\x75\xF3\x3E\x81\x78\x04\x72\x6F\x63\x41\x75\xE9\x3E\x81\x78\x08\x64\x64\x72\x65\x75\xDF\x8B\x43\x24\x03\xC1\x66\x8B\x14\x50\x4A\x8B\x43\x1C\x03\xC1\x8B\x14\x90\x8B\xC1\x03\xD0\x8B\xF2\x8B\xF9\x33\xDB\x53\x68\x61\x72\x79\x41\x68\x4C\x69\x62\x72\x68\x4C\x6F\x61\x64\x54\x51\xFF\xD2\x83\xC4\x10\x33\xC9\x68\x6C\x6C\x42\x42\x36\x88\x4C\x24\x02\x68\x33\x32\x2E\x64\x68\x75\x73\x65\x72\x54\xFF\xD0\x83\xC4\x0C\x33\xC9\x68\x6F\x78\x41\x42\x36\x88\x4C\x24\x03\x68\x61\x67\x65\x42\x68\x4D\x65\x73\x73\x54\x50\xFF\xD6\x83\xC4\x0C\x33\xD2\x33\xC9\x52\x68\x73\x67\x21\x21\x68\x6C\x65\x20\x6D\x68\x53\x61\x6D\x70\x36\x8D\x14\x24\x51\x68\x68\x65\x72\x65\x68\x68\x69\x20\x54\x36\x8D\x0C\x24\x33\xDB\x43\x53\x52\x51\x33\xDB\x53\xFF\xD0\x33\xC9\x68\x65\x73\x73\x41\x36\x88\x4C\x24\x03\x68\x50\x72\x6F\x63\x68\x45\x78\x69\x74\x36\x8D\x0C\x24\x51\x57\xFF\xD6\x33\xC9\x51\xFF\xD0";
void main()
{
printf("shellcode lenght %ld\n",(long)strlen(shellcode));
_asm{
lea eax,shellcode
push eax
ret
}
}
运行截图如下:
https://www.exploit-db.com/shellcodes/40246这个shellcode 是同样的问题