Skip to content

Instantly share code, notes, and snippets.

@williballenthin
Last active April 18, 2024 03:55
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save williballenthin/08891865082a8bd5bf921b58fa312ada to your computer and use it in GitHub Desktop.
Save williballenthin/08891865082a8bd5bf921b58fa312ada to your computer and use it in GitHub Desktop.

manual import resolution

example from 0f5d5d07c6533bc6d991836ce79daaa1:

_0:00F20012 33 D2                   xor     edx, edx
_0:00F20014 64 8B 52 30             mov     edx, fs:[edx+30h] // TEB->PEB
_0:00F20018 8B 52 0C                mov     edx, [edx+0Ch]    // PEB->LDR_DATA
_0:00F2001B 8B 52 14                mov     edx, [edx+14h]    // LDR_DATA->InMemoryOrderLinks (_LDR_DATA_TABLE_ENTRY)
                                                              // alt: 0xC: InLoadOrderLinks
                                                              // alt: 0x1C: InInitializationOrderLinks
_0:00F2001E 8B 72 28                mov     esi, [edx+28h]    // _LDR_DATA_TABLE_ENTRY.FullDllName.Buffer
                                                              // alt: 0x30: _LDR_DATA_TABLE_ENTRY.BaseDllName.Buffer

methods of encoding TEB->PEB:

mov eax, fs:0x30

0:  64 a1 30 00 00 00       mov    eax,fs:0x30

turns out that mov ebx, fs:0x30 is encoded as mov ebx,DWORD PTR fs:0x30, so see below.

rule fragment: 64 a1 30 00 00 00.

mov $reg,DWORD PTR fs:0x30

6:  64 8b 1d 30 00 00 00    mov    ebx,DWORD PTR fs:0x30
d:  64 8b 0d 30 00 00 00    mov    ecx,DWORD PTR fs:0x30
14: 64 8b 15 30 00 00 00    mov    edx,DWORD PTR fs:0x30
1b: 64 8b 35 30 00 00 00    mov    esi,DWORD PTR fs:0x30
22: 64 8b 3d 30 00 00 00    mov    edi,DWORD PTR fs:0x30 

there is no mov ebx,DWORD PTR fs:0x30, see above for alternate encoding.

rule fragment: 64 8b (1d | 0d | 15 | 35 | 3d) 30 00 00 00

mov $reg, fs:[$reg+30h]

in 0f5d5d07c6533bc6d991836ce79daaa1, we see the combination:

_0:00F20012 33 D2                   xor     edx, edx
_0:00F20014 64 8B 52 30             mov     edx, fs:[edx+30h]

not sure why the compiler did this, but we should support it.

first, to support zeroing of the register:

0:  31 c0                   xor    eax,eax
2:  31 db                   xor    ebx,ebx
4:  31 c9                   xor    ecx,ecx
6:  31 d2                   xor    edx,edx
8:  31 f6                   xor    esi,esi
a:  31 ff                   xor    edi,edi

rule fragment: 31 (c0 | db | c9 | d2 | f6 | ff)

then, to support the structure member fetch:

c:  64 8b 40 30             mov    eax,DWORD PTR fs:[eax+0x30]
10: 64 8b 43 30             mov    eax,DWORD PTR fs:[ebx+0x30]
14: 64 8b 41 30             mov    eax,DWORD PTR fs:[ecx+0x30]
18: 64 8b 42 30             mov    eax,DWORD PTR fs:[edx+0x30]
1c: 64 8b 46 30             mov    eax,DWORD PTR fs:[esi+0x30]
20: 64 8b 47 30             mov    eax,DWORD PTR fs:[edi+0x30]
24: 64 8b 58 30             mov    ebx,DWORD PTR fs:[eax+0x30]
28: 64 8b 5b 30             mov    ebx,DWORD PTR fs:[ebx+0x30]
2c: 64 8b 59 30             mov    ebx,DWORD PTR fs:[ecx+0x30]
30: 64 8b 5a 30             mov    ebx,DWORD PTR fs:[edx+0x30]
34: 64 8b 5e 30             mov    ebx,DWORD PTR fs:[esi+0x30]
38: 64 8b 5f 30             mov    ebx,DWORD PTR fs:[edi+0x30]
3c: 64 8b 48 30             mov    ecx,DWORD PTR fs:[eax+0x30]
40: 64 8b 4b 30             mov    ecx,DWORD PTR fs:[ebx+0x30]
44: 64 8b 49 30             mov    ecx,DWORD PTR fs:[ecx+0x30]
48: 64 8b 4a 30             mov    ecx,DWORD PTR fs:[edx+0x30]
4c: 64 8b 4e 30             mov    ecx,DWORD PTR fs:[esi+0x30]
50: 64 8b 4f 30             mov    ecx,DWORD PTR fs:[edi+0x30] 

rule fragment: 64 8b ?? 30

final rule fragment:

31 (c0 | db | c9 | d2 | f6 | ff) [0-8] 64 8b ?? 30

final rule fragment:

(64 a1 30 00 00 00 | 64 8b (1d | 0d | 15 | 35 | 3d) 30 00 00 00 | 31 (c0 | db | c9 | d2 | f6 | ff) [0-8] 64 8b ?? 30 )

LDR_DATA dereference

0:  8b 40 0c                mov    eax,DWORD PTR [eax+0xc]
3:  8b 5b 0c                mov    ebx,DWORD PTR [ebx+0xc]
6:  8b 49 0c                mov    ecx,DWORD PTR [ecx+0xc]
9:  8b 52 0c                mov    edx,DWORD PTR [edx+0xc]
c:  8b 76 0c                mov    esi,DWORD PTR [esi+0xc]
f:  8b 7f 0c                mov    edi,DWORD PTR [edi+0xc]
12: 8b 40 0c                mov    eax,DWORD PTR [eax+0xc]
15: 8b 43 0c                mov    eax,DWORD PTR [ebx+0xc]
18: 8b 41 0c                mov    eax,DWORD PTR [ecx+0xc]
1b: 8b 42 0c                mov    eax,DWORD PTR [edx+0xc]
1e: 8b 46 0c                mov    eax,DWORD PTR [esi+0xc]
21: 8b 47 0c                mov    eax,DWORD PTR [edi+0xc]
24: 8b 40 0c                mov    eax,DWORD PTR [eax+0xc]
27: 8b 58 0c                mov    ebx,DWORD PTR [eax+0xc]
2a: 8b 48 0c                mov    ecx,DWORD PTR [eax+0xc]
2d: 8b 50 0c                mov    edx,DWORD PTR [eax+0xc]
30: 8b 70 0c                mov    esi,DWORD PTR [eax+0xc]
33: 8b 78 0c                mov    edi,DWORD PTR [eax+0xc] 

rule fragment: 8b ?? 0c

list dereference

_0:00F2001B 8B 52 0C                mov     edx, [edx+0Ch]  ; load order
_0:00F2001B 8B 52 14                mov     edx, [edx+14h]  ; memory order
_0:00F2001B 8B 52 1C                mov     edx, [edx+1Ch]  ; init order

rule fragment: 8b ?? (0c | 14 | 1C)

name dereference:

_0:00F2001E 8B 72 28                mov     esi, [edx+28h]  ; _LDR_DATA_TABLE_ENTRY.FullDllName.Buffer
_0:00F2001E 8B 72 28                mov     esi, [edx+30h]  ; _LDR_DATA_TABLE_ENTRY.BaseDllName.Buffer

rule fragment: 8b ?? (28 | 30)

final rule

(64 a1 30 00 00 00 | 
 64 8b (1d | 0d | 15 | 35 | 3d) 30 00 00 00 |
 31 (c0 | db | c9 | d2 | f6 | ff) [0-8] 64 8b ?? 30 )
[0-8]
8b ?? 0c
[0-8]
8b ?? (0c | 14 | 1C)
[0-8]
8b ?? (28 | 30)
(64 a1 30 00 00 00 | 64 8b (1d | 0d | 15 | 35 | 3d) 30 00 00 00 | 31 (c0 | db | c9 | d2 | f6 | ff) [0-8] 64 8b ?? 30 ) [0-8] 8b ?? 0c [0-8] 8b ?? (0c | 14 | 1C) [0-8] 8b ?? (28 | 30)
rule peb_parsing
{
meta:
author = "William Ballenthin"
email = "william.ballenthin@fireeye.com"
license = "Apache 2.0"
copyright = "FireEye, Inc"
description = "Match x86 that appears to manually traverse the TEB/PEB/LDR data."
strings:
// ;; TEB->PEB
// (64 a1 30 00 00 00 | ; mov eax, fs:30
// 64 8b (1d | 0d | 15 | 35 | 3d) 30 00 00 00 | ; mov $reg, DWORD PTR fs:0x30
// 31 (c0 | db | c9 | d2 | f6 | ff) [0-8] 64 8b ?? 30 ) ; xor $reg; mov $reg, DWORD PTR fs:[$reg+0x30]
// [0-8] ; up to 8 bytes of interspersed instructions
// ;; PEB->LDR_DATA
// 8b ?? 0c ; mov eax,DWORD PTR [eax+0xc]
// [0-8] ; up to 8 bytes of interspersed instructions
// ;; LDR_DATA->OrderLinks
// 8b ?? (0c | 14 | 1C) ; mov edx, [edx+0Ch]
// [0-8] ; up to 8 bytes of interspersed instructions
// ;; _LDR_DATA_TABLE_ENTRY.DllName.Buffer
// 8b ?? (28 | 30) ; mov esi, [edx+28h]
$peb_parsing = { (64 a1 30 00 00 00 | 64 8b (1d | 0d | 15 | 35 | 3d) 30 00 00 00 | 31 (c0 | db | c9 | d2 | f6 | ff) [0-8] 64 8b ?? 30 ) [0-8] 8b ?? 0c [0-8] 8b ?? (0c | 14 | 1C) [0-8] 8b ?? (28 | 30) }
$peb_parsing64 = { (48 65 A1 60 00 00 00 00 00 00 00 | 65 (48 | 4C) 8B ?? 60 00 00 00 | 65 A1 60 00 00 00 00 00 00 00 | 65 8b ?? ?? 00 FF FF | (48 31 (c0 | db | c9 | d2 | f6 | ff) | 4D 31 (c0 | c9)) [0-16] 65 (48 | 4d | 49 | 4c) 8b ?? 60) [0-16] (48 | 49 | 4C) 8B ?? 18 [0-16] (48 | 49 | 4C) 8B ?? (10 | 20 | 30) [0-16] (48 | 49 | 4C) 8B ?? (50 | 60) }
condition:
$peb_parsing or $peb_parsing64
}

TEB->PEB (mov $reg, gs:60)

mov rax, gs:0x60    48 65 A1 60 00 00 00 00 00 00 00     48 65 A1 60 00 00 00 00 00 00 00

mov rbx, gs:0x60    65 48 8B 1D 60 00 00 00              65 (48 | 4C) 8B ?? 60 00 00 00
mov rcx, gs:0x60    65 48 8B 0D 60 00 00 00 
mov rdx, gs:0x60    65 48 8B 15 60 00 00 00 
mov rsi, gs:0x60    65 48 8B 35 60 00 00 00 
mov rdi, gs:0x60    65 48 8B 3D 60 00 00 00 

mov r8, gs:0x60     65 4C 8B 05 60 00 00 00 
mov r9, gs:0x60     65 4C 8B 0D 60 00 00 00 

mov eax, gs:0x60    65 A1 60 00 00 00 00 00 00 00        65 A1 60 00 00 00 00 00 00 00

mov ebx, gs:0x60    65 8B 1D 59 00 FF FF                 65 8b ?? ?? 00 FF FF
mov ecx, gs:0x60    65 8B 0D 59 00 FF FF 
mov edx, gs:0x60    65 8B 15 59 00 FF FF 
mov esi, gs:0x60    65 8B 35 52 00 FF FF 
mov edi, gs:0x60    65 8B 3D 4B 00 FF FF 

TEB->PEB (xor $reg, reg; mov $reg, [$reg+0x60])

xor rax, rax        48 31 C0                             48 31 (c0 | db | c9 | d2 | f6 | ff)

xor rbx, rbx        48 31 DB
xor rcx, rcx        48 31 C9
xor rdx, rdx        48 31 D2
xor rsi, rsi        48 31 F6

xor rdi, rdi        48 31 FF
xor r8, r8          4D 31 C0                             4D 31 (c0 | c9)
xor r9, r9          4D 31 C9

mov rax, gs:[rax+60h]    65 48 8B 40 60                  65 (48 | 4d | 49 | 4c) 8b ?? 60
mov rbx, gs:[rbx+60h]    65 48 8B 5B 60 
mov rcx, gs:[rcx+60h]    65 48 8B 49 60 
mov r8, gs:[r8+60h]      65 4D 8B 40 60 
mov r9, gs:[r9+60h]      65 4D 8B 49 60 

mov rax, gs:[r9+60h]     65 49 8B 41 60 
mov rbx, gs:[r9+60h]     65 49 8B 59 60 
mov r8, gs:[rax+60h]     65 4C 8B 40 60 
mov r8, gs:[rbx+60h]     65 4C 8B 43 60 

PEB->LDR_DATA (mov $reg, [$reg+0x18])

mov rax, [rax+0x18]    48 8B 40 18                        (48 | 49 | 4C) 8B ?? 18
mov rax, [rbx+0x18]    48 8B 43 18
mov rax, [rcx+0x18]    48 8B 41 18
mov rax, [r8+0x18]     49 8B 40 18
mov rax, [r9+0x18]     49 8B 41 18
mov rbx, [rax+0x18]    48 8B 58 18
mov rcx, [rax+0x18]    48 8B 48 18
mov r8, [rax+0x18]     4C 8B 40 18
mov r9, [rax+0x18]     4C 8B 48 18

LDR_DATA->*List (mov $reg, [$reg+0x10/0x20/0x30])

mov rax, [rax+0x10]    48 8B 40 10                        (48 | 49 | 4C) 8B ?? (10 | 20 | 30)                          

name dereference (mov $reg, [$reg+0x50/0x60])

mov rax, [rax+0x50]    48 8B 40 50                        (48 | 49 | 4C) 8B ?? (50 | 60)

final:

(48 65 A1 60 00 00 00 00 00 00 00 |
 65 (48 | 4C) 8B ?? 60 00 00 00   |
 65 A1 60 00 00 00 00 00 00 00    |
 65 8b ?? ?? 00 FF FF             |
 (48 31 (c0 | db | c9 | d2 | f6 | ff) | 4D 31 (c0 | c9))  [0-16] 65 (48 | 4d | 49 | 4c) 8b ?? 60)
[0-16]
(48 | 49 | 4C) 8B ?? 18
[0-16]
(48 | 49 | 4C) 8B ?? (10 | 20 | 30)
[0-16]
(48 | 49 | 4C) 8B ?? (50 | 60)
(48 65 A1 60 00 00 00 00 00 00 00 | 65 (48 | 4C) 8B ?? 60 00 00 00 | 65 A1 60 00 00 00 00 00 00 00 | 65 8b ?? ?? 00 FF FF | (48 31 (c0 | db | c9 | d2 | f6 | ff) | 4D 31 (c0 | c9))  [0-16] 65 (48 | 4d | 49 | 4c) 8b ?? 60) [0-16] (48 | 49 | 4C) 8B ?? 18 [0-16] (48 | 49 | 4C) 8B ?? (10 | 20 | 30) [0-16] (48 | 49 | 4C) 8B ?? (50 | 60)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment