这是我在看雪发布的第一篇文章,从 CSDN 到看雪也算是一个新的开始吧。
原理其实很简单,当我们用 CreateProcessW 去创建进程的时候,可以指定 lpCommandLine 、lpEnvironment 等参数的内容,并且 Windows 会将这些参数的内容复制到PEB中去。假如我们写入的 lpCommandLine 内容并非是正常的命令行,而是一段shellcode,并且再修改线程上下文去执行这段shellcode,那么不就可以达到一个进程注入的目的。
首先我们创建一个进程,命令行随便写点东西进去,看看是否能成功,
可以看到我们指定的内容已经写入到命令行了。

那么现在我们如何找到 lpCommandLine 参数在内存中的地址呢,前面说过 Windows会把这些内容写入到进程的PEB中,所以现在要先找到PEB的地址。实现也很简单,通过 NtQueryInformationProcess 这个API 即可找到。
找到的 PEB 地址为 000000B858309000。

我们用 windbg 去notepad.exe内存验证一下,确实没有错。

接下来就是通过PEB 一步一步找到 lpCommandLine 的地址了,看了一下官方定义的 PEB 结构体,里面有个成员是 ProcessParameters 。
继续跟进 ProcessParameters ,发现 CommandLine 存贮在 ProcessParameters 里面。
所以现在我们先找到 ProcessParameters 的地址,直接读即可。

再用windbg验证一下,地址正确。

顺着 ProcessParameters 地址再找到 CommandLine 地址,也是直接读取。

依旧验证。

现在我们已经找到了命令行所在的内存地址,接下来要想完整实现进程参数注入,还需解决一个问题,lpCommandLine 是一个 Windows 宽字符字符串,也就是 UTF-16 风格的 wchar_t* 字符串,若遇到连续的 0x00 那么就会被自动截断,所以shellcode不能出现 00 00。解决方法是对 shellcode 进行异或处理,把带有 00 的 shellcode 变为无 00 型,然后再编写一段 stub 拼接到 shellcode 的后面,进行循环解密,最后再 jmp 到shellcode去执行。
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。