Flag: Tornado!
Hurricane!
|
|
Topic created on: November 4, 2011 11:41 CDT by charlie .
i saw this piece of code in a malware was wondering if anyone had already seen this trick before.
The malware is using indirect api access.
Push eax
Mov eax, offset SetDlgItemA
mov eax, [eax]
add eax, 2 --> interesting bit
call eax
what are they trying to achieve here ? will adding 2 not break the code flow, is it antidebugging trick ?
but olly was successfully went past it . Will automated emulators fail on this ? any thoughts .
Thanks in advance.
Charlie
to skip some part of the prologue of the API (in this case it is likely to skip "mov edi,edi", a 2byte instruction)
|
nevar ???? how did you come to that conclusion
mov eax ,some address
mov eax ,what is pointed by that address
should fill eax with 0x8bff558b
adding 2 should make it 8bff558d
and call eax should end up with calling some r0 address
normally crash if no exception handler ???
@ charlie
are you sure API is SetDlgItemA (copy/paste/rewite error ??)
i dont find that api
lkd> x *!*Set*DlgItem*
0100123c windbg!_imp__SetDlgItemTextW = <no type information>
01001270 windbg!_imp__SetDlgItemInt = <no type information>
01d19468 symsrv!GodotFailSetDlgItemTextW = <no type information>
01d1cda0 symsrv!_imp__SetDlgItemTextA = <no type information>
01d1cd48 symsrv!_imp__SetDlgItemTextW = <no type information>
01d1cd48 symsrv!user32_SetDlgItemTextW_Ptr = <no type information>
01d0b410 symsrv!fail_SetDlgItemTextA = <no type information>
01d446e4 symsrv!Unicows_SetDlgItemTextW = <no type information>
01d195ed symsrv!_imp_load__SetDlgItemTextA = <no type information>
01d18b3e symsrv!user32_SetDlgItemTextW_Thunk = <no type information>
3d9cc27c WININET!SetCertDlgItem = <no type information>
3d93155c WININET!_imp__SetDlgItemTextW = <no type information>
662b12a4 hnetcfg!_imp__SetDlgItemTextW = <no type information>
662b12a8 hnetcfg!_imp__SetDlgItemInt = <no type information>
769c14bc USERENV!_imp__SetDlgItemTextW = <no type information>
76eb1364 TAPI32!_imp__SetDlgItemInt = <no type information>
773d14d0 COMCTL32!_imp__SetDlgItemTextW = <no type information>
774e18ec ole32!_imp__SetDlgItemTextW = <no type information>
77faf8ca SHLWAPI!SetDlgItemTextWrapW = <no type information>
77fa86f5 SHLWAPI!PathSetDlgItemPathA = <no type information>
77fb1819 SHLWAPI!PathSetDlgItemPathW = <no type information>
781314f4 urlmon!_imp__SetDlgItemTextW = <no type information>
7c9c1ce0 SHELL32!_imp__PathSetDlgItemPathW = <no type information>
7c9c1f14 SHELL32!_imp__SetDlgItemTextA = <no type information>
7c9c1d64 SHELL32!_imp__SetDlgItemTextW = <no type information>
7ca85a41 SHELL32!SetDlgItemPct = <no type information>
7ca74eaa SHELL32!PathSetDlgItemPath = <no type information>
7cb12e8d SHELL32!SetDlgItemTextWithToolTip = <no type information>
7ca859e4 SHELL32!SetDlgItemPosRange = <no type information>
7c9c1f28 SHELL32!_imp__SetDlgItemInt = <no type information>
7e42736c USER32!SetDlgItemTextW = <no type information>
7e43c972 USER32!SetDlgItemTextA = <no type information>
7e45bc09 USER32!SetDlgItemInt = <no type information>
lkd> x *!*Set*DlgItemA*
|
Apologies , the correct api name is SetDlgItemTextW
Push eax
Mov eax, offset SetDlgItemTextW
mov eax, [eax]
add eax, 2 --> interesting bit
call eax
|
.text:77D62730 ; BOOL __stdcall SetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPCWSTR lpString)
.text:77D62730 public __stdcall SetDlgItemTextW(x, x, x)
.text:77D62730 __stdcall SetDlgItemTextW(x, x, x) proc near
.text:77D62730 ; CODE XREF: SetDlgItemInt(x,x,x,x)+6Bp
.text:77D62730 ; xxxDlgDirListHelper(x,x,x,x,x,x,x)+2B6p
.text:77D62730 ; DATA XREF: ...
.text:77D62730
.text:77D62730 hDlg = dword ptr 8
.text:77D62730 nIDDlgItem = dword ptr 0Ch
.text:77D62730 lpString = dword ptr 10h
.text:77D62730
.text:77D62730 ; FUNCTION CHUNK AT .text:77D62AE5 SIZE 00000007 BYTES
.text:77D62730
.text:77D62730 8B FF mov edi, edi
.text:77D62732 55 push ebp
.text:77D62733 8B EC mov ebp, esp
.text:77D62735 FF 75 0C push [ebp+nIDDlgItem] ; nIDDlgItem
.text:77D62738 FF 75 08 push [ebp+hDlg] ; hDlg
.text:77D6273B E8 64 2B FF FF call GetDlgItem(x,x)
.text:77D62740 85 C0 test eax, eax
.text:77D62742 0F 84 9D 03 00 00 jz loc_77D62AE5
.text:77D62748 FF 75 10 push [ebp+lpString] ; lpString
.text:77D6274B 50 push eax ; hWnd
.text:77D6274C E8 8D 93 FE FF call SetWindowTextW(x,x)
.text:77D62751
.text:77D62751 loc_77D62751: ; CODE XREF: SetDlgItemTextW(x,x,x)+3B7j
.text:77D62751 5D pop ebp
.text:77D62752 C2 0C 00 retn 0Ch
.text:77D62752 __stdcall SetDlgItemTextW(x, x, x) endp
if you look at the first opcode "mov edi, edi" then you see that its a nop. so i doesn't break the code flow. on the other side when you set a breakpoint on a api it will set a int 3 at those opcode which lets me think that this is a anti debug protection as it will skip the int 3.
|
thanks for the reply
> if you look at the first opcode "mov edi, edi" then you see that its a nop. so i doesn't break the code flow.
I get this bit.
> on the other side when you set a breakpoint on a api it will set a int 3 at those opcode which lets me think that this is a anti debug protection as it will skip the int 3.
I'm not clear with this bit , you mean if i add break point at SetDlgItemTextW it adds int3 at 0x77D62730, so its skipping that bit ?
|
use of assembler or compiler produces either direct call or jmp table and if it was compiler it seems this add eax,2 will skip mov edi,edi prologue (which is completely harmless as mov edi edi is a equivalent to nop
and if you set bp Any API debuggers will set bp on this address and not two bytes below
so if you expect a break because you set a breakpoint in api wont work as expected and the call will succeed without breaking because flow is not affected by bypassing a nop
but if the code was done using ml.exe
this sequence will generate an exception and exception handler will be called
see paste below
C:\charlie>dir /b
indcall.c
indcall_jmptable.c
C:\charlie>fc indcall.c indcall_jmptable.c
Comparing files indcall.c and INDCALL_JMPTABLE.C
***** indcall.c
//#define _USER32_
#include <stdio.h>
***** INDCALL_JMPTABLE.C
#define _USER32_
#include <stdio.h>
*****
C:\charlie>cl /nologo /c indcall.c indcall_jmptable.c
indcall.c
indcall_jmptable.c
Generating Code...
c:\charlie\indcall_jmptable.c(16) : warning C4733: Inline asm assigning to 'FS:0
' : handler not registered as safe handler
c:\charlie\indcall.c(16) : warning C4733: Inline asm assigning to 'FS:0' : handl
er not registered as safe handler
C:\charlie>link /SAFESEH:no indcall.obj user32.lib
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
C:\charlie>link /nologo /SAFESEH:no indcall_jmptable.obj user32.lib
C:\charlie>dir /b
indcall.c
indcall.exe
indcall.obj
indcall_jmptable.c
indcall_jmptable.exe
indcall_jmptable.obj
C:\charlie>indcall.exe
trying some antidbg trick from openrce post by charlie
if no exception this will be printed
C:\charlie>indcall_jmptable.exe
trying some antidbg trick from openrce post by charlie
This string is printed from exception handler
^C
C:\charlie>type indcall.c
//#define _USER32_
#include <stdio.h>
#include <windows.h>
char exceptstr[] = {"This string is printed from exception handler\n"};
int main (void)
{
printf("trying some antidbg trick from openrce post by charlie\n");
__asm
{
push excepthand
push FS:[0]
mov FS:[0] ,esp
mov eax,offset SetDlgItemTextW
mov eax,[eax]
add eax,2
call eax
nop
nop
nop
}
printf ("if no exception this will be printed\n");
goto end;
__asm
{
excepthand:
nop
nop
push offset exceptstr
call printf
add esp,4
__emit 0xeb
__emit 0xfe
}
end:
return 0;
}
C:\charlie>
the _user32_ define controls if we generate direct call or jmp table
if direct call SetDlgItemTextA Will be called
if not exception will be raised
|
That was very well explained, excellent , Thanks all.
|
is it really offset SetDlgItemA or offset &SetDlgItemA?
because in the second case, you get the address that holds the dispatch to the API, like this:
offset &SetDlgItemA -> ff 25 xx xx xx xx where the xxs are the address of SetDlgItemA.
skipping 2 bytes and getting that value gives you the actual address of SetDlgItemA.
That seems to make more sense.
|
mov eax,SetDlgItemTextW will compile and get you 8bff558b
mov eax offset SetDlgItemTextW will compile and get you the ff25 XXXXXXXX
DS:[00401056]=A11025FF
EAX=00401056 (indcall_.00401056)
00401056 .- FF25 10A14000 JMP NEAR DWORD PTR DS:[<&USER32.SetDlgItemTextW>] ; USER32.SetDlgItemTextW
mov eax, &SetDlgItemTextW will not compile
indcall_pf.c(17) : error C2400: inline assembler syntax error in 'second operand
'; found 'AND'
|
I used the & in the C sense, to differentiate from some of the other posts which somehow use offset to still mean the true address. Yes, it won't compile.
What you've described matches exactly what I expect to see. The two bytes that are skipped are the jump opcode.
None of the other explanantions make any sense.
|
Charlie, can you please share the sample MD5 and SHA1 (please SHA1 at least).
Thank you.
|
Note: Registration is required to post to the forums.
|
|
|
There are 31,320 total registered users.
|
|