_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
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
.
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
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
(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: 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
_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)
_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)
(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)