Flag: Tornado! Hurricane!

 Forums >>  Target Specific - General  >>  RE doubt about indirect api access.

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.


  Nevar     November 6, 2011 13:06.44 CST
to skip some part of the prologue of the API (in this case it is likely to skip "mov edi,edi", a 2byte instruction)

  anonymouse     November 7, 2011 04:17.22 CST
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*

  charlie     November 7, 2011 06:20.30 CST
Apologies , the correct api name is SetDlgItemTextW

Push eax
Mov eax, offset SetDlgItemTextW
mov eax, [eax]
add eax, 2 --> interesting bit
call eax

  adam23     November 7, 2011 08:25.53 CST
.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                   hDlg            = dword ptr  8
.text:77D62730                   nIDDlgItem      = dword ptr  0Ch
.text:77D62730                   lpString        = dword ptr  10h
.text:77D62730                   ; FUNCTION CHUNK AT .text:77D62AE5 SIZE 00000007 BYTES
.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                   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.

  charlie     November 7, 2011 11:04.47 CST
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 ?

  anonymouse     November 7, 2011 12:31.51 CST
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

C:\charlie>fc indcall.c indcall_jmptable.c
Comparing files indcall.c and INDCALL_JMPTABLE.C
***** indcall.c
//#define _USER32_
#include <stdio.h>
#define _USER32_
#include <stdio.h>

C:\charlie>cl /nologo /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

trying some antidbg trick from openrce post by charlie
if no exception this will be printed

trying some antidbg trick from openrce post by charlie
This string is printed from exception handler
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");
                                push excepthand
                push FS:[0]
                mov FS:[0] ,esp
                mov eax,offset SetDlgItemTextW
                mov eax,[eax]
                add eax,2
                call eax
                printf ("if no exception this will be printed\n");
                goto end;
                                push offset exceptstr
                                call printf
                                add esp,4
                __emit 0xeb
                                __emit 0xfe
                return 0;


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

  charlie     November 7, 2011 13:21.09 CST
That was very well explained, excellent , Thanks all.

  PeterFerrie     November 8, 2011 11:45.44 CST
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.

  anonymouse     November 8, 2011 12:48.11 CST
mov eax,SetDlgItemTextW  will compile and get you 8bff558b

mov eax offset SetDlgItemTextW will compile and get you the ff25 XXXXXXXX

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'

  PeterFerrie     November 9, 2011 11:14.36 CST
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.

  pdrimel     March 28, 2012 16:18.09 CDT
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,038 total registered users.

Recently Created Topics
Ultimate Hacking Cha...
let 'IDAPython' impo...
set 'IDAPython' as t...
GuessType return une...
About retrieving the...
How to find specific...
How to get data depe...
Identify RVA data in...
Immunity Debugger Re...

Recent Forum Posts
How to find specific...
Problem with ollydbg
How can I write olly...
New LoadMAP plugin v...
Intel pin in loaded ...
OOP_RE tool available?
OOP_RE tool available?
Should binaries be n...
Problem with ollydbg
!findtrampoline Immu...

Recent Blog Entries

Android Application Reversing

Breaking IonCUBE VM

Anatomy of a code tracer

IAT Patcher - new tool for ...

More ...

Recent Blog Comments
nieo on:
IAT Patcher - new tool for ...

djnemo on:
Kernel debugger vs user mod...

acel on:
Kernel debugger vs user mod...

pedram on:
frida.github.io: scriptable...

capadleman on:
Using NtCreateThreadEx for ...

More ...

SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit