1.导入表隐藏
首先得先了解一个结构:
1.TEB、PEB
TEB:
TEB线程环境块:每个线程都有一个对应的TEB
PEB:
PEB进程环境块:每个进程在创建时都会有一个对应的PEB,它储存了该进程的全局状态和环境信息
这里不进行详细介绍,只了解需要用到的东西。
(1)TEB结构体
32位操作系统下,TEB结构体中偏移0x30的值是PEB结构体的地址,指向PEB结构体。我们可以通过这个获取到PEB的地址
(2)PEB结构体PEB 结构体中用到的就是这个PPEB_LDR_DATA Ldr;,偏移量是0xC,用这个可以直接获取到LDR_DATA结构体的地址。
(3)PEB_LDR_DATA结构体我们来看看这个PEB_LDR_DATA结构体是什么:
12345678typedef struct _PEB_LDR_DATA { ULONG Length; BOOL Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderMod ...
22.Inline_Hook
引入
根据上节课IAT HOOK结尾的局限性分析,自己写的函数,或者是通过LoadLibrary进来的函数在IAT 表中都是不存在的。这时候我们就需要用到Inline HOOK
Inline HOOK(内联HOOK),CE工具中的代码注入用到的就是这种HOOK。原理就是,在HOOK点修改指令,跳转到我们的函数位置,然后此时就可以获取到寄存器,堆栈信息。执行完我们自己的代码后再跳转回到原来的位置执行。
注意事项
在制作Inline hook的过程中有不少需要注意的地方:
当我们在跳转的时候可以用E8(Call),E9(Jmp)这些后面跟的地址都是需要通过公式计算的。公式:X = 要跳转到的地址 - 5 - 当前地址(X就是跳转指令后面的值)
当我们HOOK插入跳转指令的时候会修改掉一些指令,但是当前函数还没有执行这几条指令,所以在我们的函数执行完成之前还得调用回这几条指令
当我们跳转到我们自己的函数区域时可能会对堆栈、寄存器做修改,这时候就得在执行这些操作之前保存寄存器的值,在完成操作后恢复寄存器和堆栈
这里还有一个要注意的地方就是想要直接获取到自定义函数的函数首地址不能直接 ...
21.IAT_HOOK
HOOK
HOOK这个名词根据普遍的说法是勾子,是一种编程机制。当程序执行到HOOK的时候,预先挂上的勾子(HOOK)是什么就执行什么
用HOOK的目的,或者说是作用:
监控
修改某些行为
监控:可以通过HOOK来找到函数参数,返回值等信息
修改某些行为:可以用HOOK修改某些API的逻辑过程
IAT HOOK
IAT HOOK是什么?在进程加载时系统会将IAT表初始化,将里面的数据替换成函数地址(例如MessageBox)。这时我们就可以将我们自己写的函数的地址替换掉原来IAT表的地址,让程序调用MessageBox时执行我们自己定义的流程。而这个自定义函数也是有要求的,他的参数想要和原来函数的参数一样,否则调用时会错误。
那为什么能通过这种方式HOOK呢?我们来观察一下调用这个MessageBox时的反汇编:这里是个call [00FBC09C] 是个间接call,我们用内存去看看FBC09C里面是什么这是个值:75bfb1d0,那我们继续单步,直接步入这个call中
直接就跳到这个地址了,根据经验这个就是MessageBox的领空,所以[00FBC09C]存的是Mess ...
19.ShellCode_远程线程注入
远程线程注入问题引入
如果有一个程序,我们想在他里面执行我们自己的东西有什么办法呢?
方法一:
我们可以让程序执行到这个虚线的地方,然后让他跳到这个function(),执行完function后再跳回原来的下一条指令。这种方式执行的就叫做HOOK
方法二: 我们可以直接开一个线程,这个线程就用来跑外面自己的代码。
但是不管是哪种方法,都需要将外面自己的代码贴到进程A中才行
分为模块注入和代码注入
代码注入: 没有全局变量和没有使用IAT表的硬编码,放在任何位置都能执行
优点:很难被发现
缺点:写起来很麻烦(因为有全局变量地址和IAT函数地址)
模块注入:将模块一整个注入进去,这个模块可以是dll、exe等等
优点:写起来非常简单
缺点:非常容易被查杀
自己的进程加载DLL
1234// 1、自己的进程加载dllHINSTANCE hModule = LoadLibrary("InjectDll.dll");// 2、释放dllFreeLibrary(hModule);
远程线程注入
原理:
B 往A注入需要提供线程函数的地 ...
18.OD+CE练习
任务
将上节课的第八关:多级指针用OD找出。
首先用OD打开测试题,运行到第八关这里我用x64dbg。
OK,已经是第八关了,然后我们再用CE找出改变这个数值的指令在什么位置。将信息复制出来,然后在xdbg里直接跳到这个位置。(这里是没有做地址随机才可以这样)
我们来到xdbg看看是怎么情况:
跳到这个位置,发现就是将eax,移动到[rsi + 0x18]地址。在这里打上断点see see,然后在第八关点击改变数值,程序就会断在这里
到这里后看看rsi的值:
这个rsi已经是最终值了,我们看看这个[rsi+0x18]里面装了啥东西。在下面的命令窗口中输入
1dump rsi+0x18
在od中的指令是:dd rsi + 0x18
这样内存窗口就到了地址rsi+0x18的位置了。然后这个四字节应该就是数值了,但是现在还不是更改后的。我们将程序放过去,然后在查看这个位置的值。
可以看到现在这里存着的是2315,看看关卡中的值是什么:
那么这个地址就对了。再看看上面xdbg的指令,是将eax的值放到[rsi+0x18]中,先将第一次层地址关系写出来,
1值 = [rsi+0 ...
17.CE练习
任务
将完成CE自带小练习1~8这篇写的有点乱了qwq
第一关:
知识点:
精确扫描
通过数值变化确定地址
任务就是将这个100改成1000,我们可以通过CE打开这个小练习,然后扫描类型选中精确数值,数值类型从4字节开始(这个值有可能是char short int等等)我们从可能性大的DWORD 开始找,然后点击首次扫描就行了。
扫描后这里出现很多100啊,我们应该怎么找到那个100的值呢。这就是CE的精髓了,需要通过寻找变化来获取到那个地址。就例如这里的打我会让数值降低到97,那我们在精确数值那里输入97再次扫描就能看到排除了很多选项了
这个地址的97应该就是我们需要的了,直接双击一下,然后在数值那里改成1000,就可以下一步了:
第二关:
知识点:
介于两者之间的扫描类型
通过变化扫描
OK,那我们这次就可以在新的扫描前选择介于两者之间
然后回到CE的精髓就是变化,点击”打我”让这个地址的数值发生变化,然后在扫描类型中选择数值变化的方向(增加还是减少)这里”打我”了两次,第二次是-9,那就是数值减少了9,然后再进行再次扫描就扫出来了,然后直接把这个值改成题目要求的就能过了。 ...
14.win32进程创建_句柄表
win32 进程创建_句柄表
在之前的学习中,我们了解到了,程序、镜像(ImageBuffer)、进程。那么这三个有什么区别呢?
通俗来讲程序就是写好的.exe但是还没有运行,死的一个东西;镜像是将程序按照PE格式拉伸贴到4GB空间中的东西,而进程就是这个镜像跑起来后的东西。当eip”给到”这个ImageBufffer时这个就运行起来了
父进程创建子进程,父进程挂了子进程不会挂
一、进程创建的过程
步骤一:当系统启动后,会创建一个进程:Explorer.exe 也就是桌面进程。
步骤二:当用户双击某一个exe时,Explorer 进程使用CreateProcess函数创建被双击的exe,也就是说:我们在桌面上双击创建的进程都是Explorer进程的子进程。
我们可以通过XueTr.exe ,查看那些进程是由Explorer创建的。
二、CreateProcess函数做了什么123456789101112BOOL CreateProcess( LPCTSTR lpApplicationName, // name of executable m ...
12.win32事件
内核对象
1、什么是内核对象
内核对象:
进程
线程
文件
文件映射
事件
互斥体等待
2、事件内核创建
1234567891011HANDLE CreateEventA( [in, optional] LPSECURITY_ATTRIBUTES lpEventAttributes, [in] BOOL bManualReset, [in] BOOL bInitialState, [in, optional] LPCSTR lpName);// 创建事件内核对象HANDLE g_hEvent = CreateEvent(NULL,TRUE,FALSE,"XYZ");// 创建互斥体对象HANDLE g_hMutex = CreateMutex(NULL,FALSE,"XYZ")
CreateEvent 函数参数解释:
lpEventAttributes : 安全属性
bManualReset ...