ShellCode编写手册
注意事项 在Windows中,ASLR_(Address Space Layout Randomization)(内存随机化保护)的存在使得内存地址随机化成为常态。PE文件通过其重定向表(.reloc节)能够适应这种随机化,使得程序在每次启动时都能正确处理地址引用。 shellcode作为一段纯机器码,不存在重定向表。在编写时,不能依赖固定的内存地址,由于ASLR的作用,这些地址在重启后会发生改变,导致shellcode失效。 也就是说,在开启了ASLR的系统上,在Shellcode中不能直接通过名称调用Windows API,也不能通过DLL base + 偏移的方式调用API。如果没有启用 ASLR,Windows 加载器会尝试将 DLL 加载到其 PE 头中 ImageBase 字段指定的地址。并且由于系统 DLL 是共享的,在不同进程中它们会被映射到相同的虚拟地址。 由于Shellcode没有 rdata段,不能使用全局变量,所有的变量只能在函数的内部栈上分配,使用相对寻址而非绝对寻址。 工作可以分为三步: 在内存中查找需要调用的 DLL 文件。 解析 DLL 的导出表。 通过导出表名称对比定位到函数指针。 为了简化第3步,可以先获取两个关键API(GetProcessAddress、LoadLibrary) 第一步:获取 Kernel32.DLL 地址 Shellcode 中通常需要调用操作系统API,为了使该代码可以在不同的机器上运行,避免写死地址时由于地址随机化导致找不到的问题,需要动态定位Windows API地址。 参考:Finding Kernel32 Base and Function Addresses in Shellcode - ired.team 建议动手通过 windbg 跟一遍获取流程,会加深对偏移的理解。 PEB (Process Environment Block) 是 Windows 操作系统中每个进程都有的一个数据结构,每个进程都有一个唯一的PEB。PEB中存储了进程的各种关键信息:进程的基本参数如进程的镜像基址、命令行参数、环境变量等。PEB中还存储了进程加载的模块列表(LoaderData),这个列表记录了所有被加载到进程空间的DLL信息。 同理,TEB (Thread Environment Block) 是保存线程相关的结构体,一个进程只有一个PEB,但可以有多个TEB 对应多个线程,每个TEB都持有一个指向其所属进程PEB的指针,这样线程就能访问进程级的信息。 通过获取PEB结构,遍历其中的模块列表,可以找出所需要的DLL模块。 开始之前,先细化工作: 获取 PEB 结构体的地址 https://en.wikipedia.org/wiki/Win32_Thread_Information_Block ...