windbg查看dll基址
fs寄存器 -> TEB -> PEB -> PEB_LDR_DATA -> LIST_ENTRY -> LDR_DATA_TABLE_ENTRY -> dll_base
syscall
首先写一个简单的syscall的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <Windows.h> #include "winternl.h" #pragma comment(lib, "ntdll")
EXTERN_C NTSTATUS SysNtCreateFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
int main() { FARPROC addr = GetProcAddress(LoadLibraryA("ntdll"), "NtCreateFile");
OBJECT_ATTRIBUTES oa; HANDLE fileHandle = NULL; NTSTATUS status = NULL; UNICODE_STRING fileName; IO_STATUS_BLOCK osb;
RtlInitUnicodeString(&fileName, (PCWSTR)L"\\??\\c:\\temp\\test.txt"); ZeroMemory(&osb, sizeof(IO_STATUS_BLOCK)); InitializeObjectAttributes(&oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
SysNtCreateFile( &fileHandle, FILE_GENERIC_WRITE, &oa, &osb, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
return 0; }
|
编译生成exe文件,然后丢进windbg里面进行调试
windbg常用的几个指令
- bp(breakpoint)
- g(goto)
- dt(dump using type information)
- dv(dump local variables)
- k(stacktrace)
这样的话,我们先来分析下TEB的数据结构dt _TEB
可以发现在0x060的偏移处存放的是进程环境块PEB的指针
接着我们继续跟进,插卡PEB的数据结构dt _PEB
可以看到0x018的偏移处存放的是PEB_LDR_DATA结构体的指针
继续跟进PEB_LDR_DATA数据结构
可以看到在0x020的偏移出存放的是_LIST_ENTRY指针
根据其名字变量名InMemoryOrderModuleList
可以看出是按照内存中顺序的模块链表
继续跟进就能看到该_LIST_ENTRY
为双向链表
既然是双向链表,那肯定继续指出了下一步的指针,但这里无法明确的看出,我们需要去MSDN进行查询
通过查询MSDN
可以知道,这里对应的是LDR_DATA_TABLE_ENTRY
这个结构体
那我们继续跟进这个结构体dt _LDR_DATA_TABLE_ENTRY
,也就是该链表实际指向的内容
可以看到这里偏移0x018的位置,存放的就是DLL基地址,同时还存有FullDllName和BaseDllName可以帮助我们区分是哪个DLL
代码遍历模块链表
模块链表是一个双向循环链表,以下以遍历InLoadOrderModuleList举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>
typedef struct _LIST_ENTRY { _LIST_ENTRY* Flink; _LIST_ENTRY* Blink; }_LIST_ENTRY;
typedef struct _UNICODE_STRING { unsigned short Length; unsigned short MaximumLength; wchar_t* Buffer; };
int main() { int* pPEB = NULL;
__asm { push eax mov eax,fs:[0x30] mov pPEB,eax pop eax }
int* pIDR = (int*)(*(pPEB + 0x03));
_LIST_ENTRY* pInLoadOrderModuleList = (_LIST_ENTRY*)(pIDR + 0x03);
_LIST_ENTRY* pHead, *p; p = pHead = pInLoadOrderModuleList->Flink;
int count = 0; do { printf("%d: ", count++); _UNICODE_STRING* pBaseName = (_UNICODE_STRING*)(((int)p) + 0x2c); if (pBaseName->Buffer) wprintf(L"%s ", pBaseName->Buffer); printf("0x%x\n", *((int*)(((int)p) + 0x18))); p = p->Flink; } while (p != pHead);
return 0; }
|