0

In the disassembly of user32.dll, I see tables of function pointers like the one below in .text section. It doesn't look like vftable or switch/case table. Can you please give any insight about what this table is for?

.text:6BA87530 off_6BA87530    dd offset sub_6BAD4C1E  
.text:6BA87534 dword_6BA87534  dd 0                    
.text:6BA87538                 dd offset sub_6BA890C6
.text:6BA8753C                 align 10h
.text:6BA87540                 dd offset sub_6BAD4B0A
.text:6BA87544                 align 8
.text:6BA87548                 dd offset sub_6BAD4730
.text:6BA8754C                 align 10h
.text:6BA87550                 dd offset sub_6BA890C6
.text:6BA87554                 align 8
.text:6BA87558                 dd offset sub_6BA890C6
.text:6BA8755C                 align 10h
.text:6BA87560                 dd offset sub_6BA890C6
.text:6BA87564                 align 8
.text:6BA87568                 dd offset sub_6BACCCB6
.text:6BA8756C                 align 10h
.text:6BA87570                 dd offset sub_6BAD5EE1
.text:6BA87574                 align 8
.text:6BA87578                 dd offset sub_6BAE82EE
.text:6BA8757C                 align 10h
.text:6BA87580                 dd offset sub_6BA9D3D5
.text:6BA87584                 align 8
.text:6BA87588                 dd offset sub_6BAE2428
.text:6BA8758C                 align 10h
.text:6BA87590                 dd offset sub_6BAE83F1
.text:6BA87594                 align 8
.text:6BA87598                 dd offset sub_6BAA9760
.text:6BA8759C                 align 10h
.text:6BA875A0                 dd offset sub_6BA9F560
.text:6BA875A4                 align 8
.text:6BA875A8                 dd offset loc_6BA8DA5B
.text:6BA875AC                 align 10h
.text:6BA875B0                 dd offset sub_6BA890C6
.text:6BA875B4                 align 8
.text:6BA875B8                 dd offset sub_6BA87CA1
.text:6BA875BC                 align 10h
.text:6BA875C0                 dd offset sub_6BAD41C5
.text:6BA875C4                 align 8
.text:6BA875C8                 dd offset sub_6BA893E9
.text:6BA875CC                 align 10h
.text:6BA875D0                 dd offset sub_6BA9B419
.text:6BA875D4                 align 8
.text:6BA875D8                 dd offset sub_6BA87B11
.text:6BA875DC                 align 10h
.text:6BA875E0                 dd offset sub_6BAEFB8A
.text:6BA875E4                 align 8
.text:6BA875E8 off_6BA875E8    dd offset sub_6BAD4BFD  

The start and end addresses (off_6BA87530, off_6BA875E8) are referenced by code snippets like

.text:6BA8FFE8                 push    eax
.text:6BA8FFE9                 push    offset off_6BA87530
.text:6BA8FFEE                 push    eax
.text:6BA8FFEF                 push    offset off_6BA875E8
.text:6BA8FFF4                 call    ds:RtlInitializeNtUserPfn

or

.text:6BA9D84F                 mov     esi, ds:off_6BA87530[eax*8]
.text:6BA9D856                 mov     [ebp+var_40], esi
.text:6BA9D859                 mov     eax, ds:dword_6BA87534[eax*8]
.text:6BA9D860                 mov     [ebp+var_3C], eax
.text:6BA9D863                 jmp     loc_6BA87A7C 

Thanks.

UPDATE Adding the code snippets of functions referred to by first two addresses: sub_6BAD4C1E, sub_6BA890C6

enter image description here

enter image description here

2
  • Could you show an example of what the table entries are pointing at? That might gives us a clue (i.e. regular function, thunk, runtime info...). For example, the code might be registering exception thunks.
    – DarthGizka
    Apr 27, 2016 at 7:11
  • the first one is USER32!ScrollBarWndProcA the second one is USER32!DefWindowProcA doesn't your ida pick up the symbol file for user32.dll ? if it doesnt load the user32.dll in windbg as a dump file windbg -z user32.dll load the symbol and compare addresses
    – blabb
    Apr 29, 2016 at 20:22

1 Answer 1

0

RtlInitializeUserPfn rep movsds (memcpy()) those address to ntdll!_NtUserPfn (most of the addresses are Windowsproc buttonproc callbacks

what windows version are you on iirc these functions weren't implemented until win 8 see below

0:000> u ntdll!NtdllDispatchDefWindowProc_W l1

ntdll!NtdllDispatchDefWindowProc_W:
77e039f4 ff25ac80e377    jmp     dword ptr [ntdll!NtUserPfn+0xac (77e380ac)]

0:000> ln poi(77e380ac) ntdll!UninitUser32Proc ()

0:000> uf ntdll!UninitUser32Proc

ntdll!UninitUser32Proc:
77e03aa4 6896a0da77      push    offset ntdll! ?? ::FNODOBFM::`string' (77daa096)
77e03aa9 6a00            push    0
77e03aab 6a00            push    0
77e03aad e884dff7ff      call    ntdll!DbgPrintEx (77d81a36)
77e03ab2 83c40c          add     esp,0Ch
77e03ab5 cc              int     3
77e03ab6 680d0000c0      push    0C000000Dh
77e03abb 6aff            push    0FFFFFFFFh
77e03abd e8062efaff      call    ntdll!NtTerminateProcess (77da68c8)
77e03ac2 33c0            xor     eax,eax
77e03ac4 c3              ret

0:000> da 77daa096

77daa096  "User32 init not called"

windows 7 user32!DllInit routine fills the array itself

user32!InitializeNtdllUserPfn:
77d2d787 b86606d277      mov     eax,offset user32!ImeWndProcW (77d20666)
77d2d78c a36096d777      mov     dword ptr [user32!gDefaultClasses+0x100 (77d79660)],eax
77d2d791 a30091d777      mov     dword ptr [user32!g_pfnImeWndProcW (77d79100)],eax
77d2d796 b9063fd677      mov     ecx,offset user32!EditWndProcW (77d63f06)
77d2d79b 33c0            xor     eax,eax
77d2d79d c7056495d7770449d377 mov dword ptr [user32!gDefaultClasses+0x4 (77d79564)],offset user32!ButtonWndProcW (77d34904)
77d2d7a7 c7058895d7779de0d577 mov dword ptr [user32!gDefaultClasses+0x28 (77d79588)],offset user32!ComboBoxWndProcW (77d5e09d)
77d2d7b1 c705ac95d777ae0dd477 mov dword ptr [user32!gDefaultClasses+0x4c (77d795ac)],offset user32!ListBoxWndProcW (77d40dae)
77d2d7bb c705d095d777c15bd477 mov dword ptr [user32!gDefaultClasses+0x70 (77d795d0)],offset user32!DefDlgProcW (77d45bc1)
77d2d7c5 890df495d777    mov     dword ptr [user32!gDefaultClasses+0x94 (77d795f4)],ecx
77d2d7cb c7051896d777ae0dd477 mov dword ptr [user32!gDefaultClasses+0xb8 (77d79618)],offset user32!ListBoxWndProcW (77d40dae)
77d2d7d5 c7053c96d777df14d477 mov dword ptr [user32!gDefaultClasses+0xdc (77d7963c)],offset user32!MDIClientWndProcW (77d414df)
77d2d7df c7058496d7778b3ad377 mov dword ptr [user32!gDefaultClasses+0x124 (77d79684)],offset user32!StaticWndProcW (77d33a8b)
77d2d7e9 c7055c97d7777d50d277 mov dword ptr [user32!gDefaultClasses+0x1fc (77d7975c)],offset user32!DefWindowProcW (77d2507d)
77d2d7f3 c7053891d777f8b5d377 mov dword ptr [user32!g_pfnEditWndProcA (77d79138)],offset user32!EditWndProcA (77d3b5f8)
77d2d7fd 890d2091d777    mov     dword ptr [user32!g_pfnEditWndProcW (77d79120)],ecx
77d2d803 40              inc     eax
77d2d804 c3              ret

while some other user32.dll > win7 calls a forwarded import in ntdll

user32!InitializeNtdllUserPfn:
00000001`80022e98 4c8bdc          mov     r11,rsp
00000001`80022e9b 4883ec38        sub     rsp,38h
00000001`80022e9f 4983631000      and     qword ptr [r11+10h],0
00000001`80022ea4 4983630800      and     qword ptr [r11+8],0
00000001`80022ea9 4983631800      and     qword ptr [r11+18h],0
00000001`80022eae 488d05eba50000  lea     rax,[user32!pfnClientWorker (00000001`8002d4a0)]
00000001`80022eb5 bab8000000      mov     edx,0B8h
00000001`80022eba 49c743f058000000 mov     qword ptr [r11-10h],58h
00000001`80022ec2 4c8d0537a60000  lea     r8,[user32!pfnClientW (00000001`8002d500)]
00000001`80022ec9 488d0df0a60000  lea     rcx,[user32!pfnClientA (00000001`8002d5c0)]
00000001`80022ed0 448bca          mov     r9d,edx
00000001`80022ed3 498943e8        mov     qword ptr [r11-18h],rax
00000001`80022ed7 ff155b520800    call    qword ptr [user32!_imp_RtlInitializeNtUserPfn (00000001`800a8138)]

with windbg you can retrieve all the wndprocs that are memcpied thus using some script like below

.for(r $t0=0 ; @$t0 < (60+c0+c0) ; r $t0 = @$t0+8) { .printf "%y %y\n" , user32!pfnClientWorker+@$t0 , poi(user32!pfnClientWorker +@$t0) }

which would get you result like this (read with the disassembly posted above of a random(winblue) user32.dll that implements the forwarded import

user32!pfnClientWorker (00000001`8002d4a0) user32!ButtonWndProcWorker (00000001`8001c760)
user32!pfnClientWorker+0x8 (00000001`8002d4a8) user32!ComboBoxWndProcWorker (00000001`80060c38)
user32!pfnClientWorker+0x10 (00000001`8002d4b0) user32!ListBoxWndProcWorker (00000001`80077fa0)
user32!pfnClientWorker+0x18 (00000001`8002d4b8) user32!DefDlgProcWorker (00000001`8001ebf0)
user32!pfnClientWorker+0x20 (00000001`8002d4c0) user32!EditWndProcWorker (00000001`80031354)
user32!pfnClientWorker+0x28 (00000001`8002d4c8) user32!ListBoxWndProcWorker (00000001`80077fa0)
user32!pfnClientWorker+0x30 (00000001`8002d4d0) user32!MDIClientWndProcWorker (00000001`80036400)
user32!pfnClientWorker+0x38 (00000001`8002d4d8) user32!StaticWndProcWorker (00000001`8001f0a0)
user32!pfnClientWorker+0x40 (00000001`8002d4e0) user32!ImeWndProcWorker (00000001`80008e14)
user32!pfnClientWorker+0x48 (00000001`8002d4e8) user32!DefWindowProcWorker (00000001`80008ef0)
user32!pfnClientWorker+0x50 (00000001`8002d4f0) user32!CtfHookProcWorker (00000001`80005d44)
user32!pfnClientWorker+0x58 (00000001`8002d4f8) 90909090`90909090
user32!pfnClientW (00000001`8002d500) user32!ScrollBarWndProcW (00000001`8005f6cc)
user32!pfnClientW+0x8 (00000001`8002d508) user32!DefWindowProcW (00000001`80002d60)
user32!pfnClientW+0x10 (00000001`8002d510) user32!MenuWndProcW (00000001`8005f574)
user32!pfnClientW+0x18 (00000001`8002d518) user32!DesktopWndProcW (00000001`8005f138)
user32!pfnClientW+0x20 (00000001`8002d520) user32!DefWindowProcW (00000001`80002d60)
user32!pfnClientW+0x28 (00000001`8002d528) user32!DefWindowProcW (00000001`80002d60)
user32!pfnClientW+0x30 (00000001`8002d530) user32!DefWindowProcW (00000001`80002d60)
user32!pfnClientW+0x38 (00000001`8002d538) user32!ButtonWndProcW (00000001`8001c6cc)
user32!pfnClientW+0x40 (00000001`8002d540) user32!ComboBoxWndProcW (00000001`80060ad8)
user32!pfnClientW+0x48 (00000001`8002d548) user32!ComboListBoxWndProcW (00000001`80077ed4)
user32!pfnClientW+0x50 (00000001`8002d550) user32!DefDlgProcW (00000001`8001eb7c)
user32!pfnClientW+0x58 (00000001`8002d558) user32!EditWndProcW (00000001`800312c4)
user32!pfnClientW+0x60 (00000001`8002d560) user32!ComboListBoxWndProcW (00000001`80077ed4)
user32!pfnClientW+0x68 (00000001`8002d568) user32!MDIClientWndProcW (00000001`8003634c)
user32!pfnClientW+0x70 (00000001`8002d570) user32!StaticWndProcW (00000001`8001f050)
user32!pfnClientW+0x78 (00000001`8002d578) user32!ImeWndProcW (00000001`80008da0)
user32!pfnClientW+0x80 (00000001`8002d580) user32!DefWindowProcW (00000001`80002d60)
user32!pfnClientW+0x88 (00000001`8002d588) user32!fnHkINLPCWPSTRUCTW (00000001`80003da0)
user32!pfnClientW+0x90 (00000001`8002d590) user32!fnHkINLPCWPRETSTRUCTW (00000001`80012c40)
user32!pfnClientW+0x98 (00000001`8002d598) user32!DispatchHookW (00000001`80003d20)
user32!pfnClientW+0xa0 (00000001`8002d5a0) user32!DispatchDefWindowProcW (00000001`8000ed34)
user32!pfnClientW+0xa8 (00000001`8002d5a8) user32!DispatchClientMessage (00000001`800038f0)
user32!pfnClientW+0xb0 (00000001`8002d5b0) user32!MDIActivateDlgProcA (00000001`80080100)
user32!pfnClientW+0xb8 (00000001`8002d5b8) 90909090`90909090
user32!pfnClientA (00000001`8002d5c0) user32!ScrollBarWndProcA (00000001`8005f6b0)
user32!pfnClientA+0x8 (00000001`8002d5c8) user32!DefWindowProcA (00000001`8000ad38)
user32!pfnClientA+0x10 (00000001`8002d5d0) user32!MenuWndProcA (00000001`8005f558)
user32!pfnClientA+0x18 (00000001`8002d5d8) user32!DesktopWndProcA (00000001`8005f11c)
user32!pfnClientA+0x20 (00000001`8002d5e0) user32!DefWindowProcA (00000001`8000ad38)
user32!pfnClientA+0x28 (00000001`8002d5e8) user32!DefWindowProcA (00000001`8000ad38)
user32!pfnClientA+0x30 (00000001`8002d5f0) user32!DefWindowProcA (00000001`8000ad38)
user32!pfnClientA+0x38 (00000001`8002d5f8) user32!ButtonWndProcA (00000001`8005c620)
user32!pfnClientA+0x40 (00000001`8002d600) user32!ComboBoxWndProcA (00000001`80060970)
user32!pfnClientA+0x48 (00000001`8002d608) user32!ComboListBoxWndProcA (00000001`80077e40)
user32!pfnClientA+0x50 (00000001`8002d610) user32!DefDlgProcA (00000001`8006a3d8)
user32!pfnClientA+0x58 (00000001`8002d618) user32!EditWndProcA (00000001`8006ec64)
user32!pfnClientA+0x60 (00000001`8002d620) user32!ComboListBoxWndProcA (00000001`80077e40)
user32!pfnClientA+0x68 (00000001`8002d628) user32!MDIClientWndProcA (00000001`80081450)
user32!pfnClientA+0x70 (00000001`8002d630) user32!StaticWndProcA (00000001`80086268)
user32!pfnClientA+0x78 (00000001`8002d638) user32!ImeWndProcA (00000001`8008dad0)
user32!pfnClientA+0x80 (00000001`8002d640) user32!DefWindowProcA (00000001`8000ad38)
user32!pfnClientA+0x88 (00000001`8002d648) user32!fnHkINLPCWPSTRUCTA (00000001`8008c850)
user32!pfnClientA+0x90 (00000001`8002d650) user32!fnHkINLPCWPRETSTRUCTA (00000001`8008c790)
user32!pfnClientA+0x98 (00000001`8002d658) user32!DispatchHookA (00000001`8008bea0)
user32!pfnClientA+0xa0 (00000001`8002d660) user32!DispatchDefWindowProcA (00000001`8008be84)
user32!pfnClientA+0xa8 (00000001`8002d668) user32!DispatchClientMessage (00000001`800038f0)
user32!pfnClientA+0xb0 (00000001`8002d670) user32!MDIActivateDlgProcA (00000001`80080100)
user32!`string' (00000001`8002d678) 4c4e4e49`576d6d49
1
  • Thanks. I am using Windows 10. Does it mean that RtlInitializeNtUserPfn takes the start and end addresses of an array and copy the callback function addresses from that array to _NtUserPfn? If yes, how would that array/data structure look like in the source code of user32.dll? My goal is to understand and distinguish among various tables (vftable/jump table/exception handler table) of function pointers in a dis-assembled binary.
    – ssultana
    Apr 27, 2016 at 23:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.