shellcode
1. はじめに
LabyREnth CTF Windows Track のLv6の問題 (Shellcode) にて. 覚書として.
2. shllcode
Ambrosius.exeを対象に行う.
> cdb Ambrosius.exe
0:000> dt _TEB
ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
(省略)
0:000> dt _PEB -r2
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 BitField : UChar
+0x003 ImageUsesLargePages : Pos 0, 1 Bit
+0x003 IsProtectedProcess : Pos 1, 1 Bit
+0x003 IsImageDynamicallyRelocated : Pos 2, 1 Bit
+0x003 SkipPatchingUser32Forwarders : Pos 3, 1 Bit
+0x003 IsPackagedProcess : Pos 4, 1 Bit
+0x003 IsAppContainer : Pos 5, 1 Bit
+0x003 IsProtectedProcessLight : Pos 6, 1 Bit
+0x003 SpareBits : Pos 7, 1 Bit
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void
+0x028 ShutdownInProgress : UChar
+0x02c ShutdownThreadId : Ptr32 Void
(省略)
0:000> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x008 InMemoryOrderLinks : _LIST_ENTRY
+0x010 InInitializationOrderLinks : _LIST_ENTRY
+0x018 DllBase : Ptr32 Void
+0x01c EntryPoint : Ptr32 Void
+0x020 SizeOfImage : Uint4B
(省略)
0:000> r @$t0 = poi(poi(fs:30)+0C)+14
0:000> dt _LDR_DATA_TABLE_ENTRY poi(@$t0)-8
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4e2b60 - 0x776fab4c ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x4e2b68 - 0x776fab54 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x018 DllBase : 0x00400000 Void
+0x01c EntryPoint : 0x004010e7 Void
+0x020 SizeOfImage : 0x2000
+0x024 FullDllName : _UNICODE_STRING "C:\Users\akabane\Desktop\Ambrosius.exe"
+0x02c BaseDllName : _UNICODE_STRING "Ambrosius.exe"
(省略)
0:000> dt _LDR_DATA_TABLE_ENTRY poi(poi(@$t0))-8
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4e3028 - 0x4e2c60 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x4e3030 - 0x4e2c68 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x4e3368 - 0x776fab5c ]
+0x018 DllBase : 0x775f0000 Void
+0x01c EntryPoint : (null)
+0x020 SizeOfImage : 0x17b000
+0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\SYSTEM32\ntdll.dll"
+0x02c BaseDllName : _UNICODE_STRING "ntdll.dll"
(省略)
0:000> dt _LDR_DATA_TABLE_ENTRY poi(poi(poi(@$t0)))-8
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x4e3358 - 0x4e2b60 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x4e3360 - 0x4e2b68 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x4e3dc8 - 0x4e3368 ]
+0x018 DllBase : 0x74860000 Void
+0x01c EntryPoint : 0x74873980 Void
+0x020 SizeOfImage : 0xe0000
+0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\SYSTEM32\KERNEL32.DLL"
+0x02c BaseDllName : _UNICODE_STRING "KERNEL32.DLL"
(省略)
これよりDllBaseは0x74860000である.
0:000> lm
start end module name
00400000 00402000 image00400000 (deferred)
71c30000 71cc2000 apphelp (deferred)
74860000 74940000 KERNEL32 (deferred)
(省略)
lmコマンド(List Loaded Modules)で確認すると上記したDllBaseとkernel32.dllのアドレスが一致している.
つまり最初のコードを以下のように解釈される(説明の都合上番号を振る).
(1) mov eax, large fs:30h
(2) mov eax, [eax+0Ch]
(3) mov eax, [eax+14h]
(4) mov eax, [eax]
(5) mov eax, [eax]
(6) mov eax, [eax+10h]
(7) retn
(1) fs:30h -> PEB
(2) PEB -> Ldr
(3) Ldr -> InMemoryOrderModuleList.Flink
(4),(5)InMemoryOrderModuleList.Flink
(6) _LDR_DATA_TABLE_ENTRY -> DllBase
Cで記述すると以下のようになる.
なお最後にDllBaseではなくReserved2[0]を呼び出しているのは, FlinkによりLDR_DATA_TABLE_ENTRYが+0x8だけずれているからである.
これはAPIのハッシュを計算している関数である. 引数としてIMAGE_EXPORT_DIRECTORYのAddressOfNamesをとる.
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
APIハッシュの計算するスクリプトを以下に記す. IDAに読み込ませるために,列挙型を定義している.
IDAにAPIハッシュを読み込ませる
・> python api_hash.py C:\Windows\System32\kernel32.dll > api_hash.h
・FIle -> Load file -> Parse C header file ... -> api_hash.h
・[Enum] -> Define a new enumeration type (Ins) -> Add standard enum by enum name -> ヘッダファイルを選択
・APIのハッシュ値を選択 -> Symbolic constant -> hash_kernel32_***
3. 補足
.cls : clear all of the text from the Debugger Command window
4. 参考
・Harmony Security: Retrieving Kernel32's Base Address
・PEB_LDR_DATA structure (Windows)
・Windowsで電卓を起動するシェルコードを書いてみる - ももいろテクノロジー
・リバースエンジニアリング入門(1):シェルコードから始めるマルウェア解析 (1/2) - @IT
kmdnet