如果是win10直接下载windbg预览版,预览版只有win10才能用,我的是win7所以下载的是老版本的,老版本去官网中的win10 sdk中下载 链接:https://developer.microsoft.com/zh-cn/windows/downloads/sdk-archive
下载后会有x86和64位两个版本,两个版本都要配置符号路径,否则只能使用一个版本
快捷键 ctrl+s弹出符号路径配置,路径写上:srvd:\symbolslocalhttp://msdl.microsoft.com/download/symbols**,这样如果相关符号表在d:\symbolslocal目录没有找到的话,Windbg会自动在Microsoft的Symbol Servers上下载
注意两个版本,路径修改一下盘符就可以了 ,这样路径就不一样,两个版本就可以用了
1利用微软提供的windbg找到不同线程对应的信息结构体,拿到相关信息
MASM中默认是fs:error,也就是默认不能使用fs段寄存器,因此要在masm中使用它时必须先assume fs:nothing。fs 段寄存器初始化后,指向当前活动线程的_TEB结构(线程结构),即_TEB首地址
2通过加30的位置拿到PEB结构体mov eax, fs:[30h]
3拿到通过PEB拿到_PEB_LDR_DATA的结构体
4通过_PEB_LDR_DATA拿到保存模块信息结构体的链表_LIST_ENTRY(有按3种不同方式排列的链表)
5_LIST_ENTRY实际指向的结构体类型是拿到模块信息(注意不同链表内的指针取内容拿到取的是结构体不同的位置)
结构体链表结构如下(和c语言一样):
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,所以从10到30的位置偏移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 ;平栈
通过断开线程信息中的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