最近看的一篇文章,简单来说就是把shellcode放到PE文件里,在PE文件开始执行的时候先跳到shellcode段,执行完shellcode之后再跳回来
https://github.com/NetSPI/PESecurity
1 | Import-Module .\Get-PESecurity.psm1 |
用VC6编译一个helloworld
是不开启ASLR的
ASLR(地址空间配置随机加载),就不照抄百度百科了,想看的师傅可以查一下
个人理解就是exe每次载入栈内存分配的地址不一样、
一个未开启ASLR的程序每次载入栈顶栈底都是一样的,开启了ASLR的程序每次载入栈顶栈底每次都不一样
这里就不演示了,直接把程序放进x32dbg,然后Ctrl+F2观察一下堆栈区就可以看到
下面写一下具体方法
这里就用上面的helloworld来示范
需要用到LoadPE,可以在吾爱上面下载
PE编辑器->选择PE文件->编辑区段,添加区段
添加一个.msg区段,这个名字可以随便改
虚拟地址和物理偏移会自动填好
虚拟大小和物理大小填一样就行,根据shellcode的长度填,填多了也没关系能放下shellcode就行
至于这个标就是这段内存中的一些属性,默认的就行
修改好就是上面这样子
这时候这个PE文件已经打不开了,可以用010Editor找到2A000在后面添加1280字节进去,注意上面的500是16进制
加多了也没事
有些时候不一定是在文件末尾,还是要看给出的物理偏移来修改,像这里才2A000其实已经有东西了,后面可以删掉,因为要存放shellcode,添加1280字节到2A500就行
下面用msf生成messagebox的payload
1 | msfvenom -p windows/messagebox TEXT="helloworld" -f hex |
生成的shellcode放到.msg段里面
顺便说一下这个编辑器用Ctrl+Shift+v粘贴二进制,之前找这个还花了一点时间
打开x32dbg,查看.msg段的起始地址
点开查看payload
接着回到程序开始执行的地方
把第一行命令改为jmp到.msg段,jmp需要五个字节,会覆盖三行命令
需要记住这三行命令,其实修改这个就和手搓免杀那篇文章差不多
之后去.msg段把最后那行去掉
因为这个CALL是退出进程的函数,执行到这里程序就退出了,所以要去掉
现在还不能直接贴上三条命令,经过shellcode之后,堆栈已经变了,再PUSH就不会到程序原来的位置
需要堆栈平衡一下
因为未开启ASLR所以堆栈区每次在载入都是不变的,只需要记住程序开始时的栈顶栈底执行完shellcode之后修改一下就可以堆栈平衡
改成这样打好补丁
点击确定之后会打印helloworld,程序正常执行
最简单的方法就是把.reloc这个段删了,这样ASLR就无了,每次的地址也都是一样的
然后就是正常的
这里用powershell32位示范
创建段都和上面一样
需要注意的是修改完或一段时候打开程序后,执行程序的地址就会不一样,并且每次执行堆栈区都会不一样
对比
仔细观察CALL会发现只有前面两位有变化,修改的时候可以查看一下下面的汇编,找到前面两位
然后和上面一样在shellcode最后执行被覆盖的指令然后jmp回来,之前说过CALL和JMP都是靠偏移的,所以不用担心地址改变程序跳不到正确的地方
如果需要esp和ebp的值可以在shellcode之前先把这两个值保存在内存里,到shellcode执行结束之后再重新改回去
具体就不写了还是有点懒,别的都差不多的
PE文件里面出现的00000000,每个PE里面或多或少都会有,把shellcode放到这些地方
这种方法可以使程序本身大小不变
注意shellcode的长度要小于代码空洞
网上有工具自动找代码空洞,但是那个工具装不起来就只能手动了
找到后首先确定在哪个区段里面,如果是数据段资源段这些的要修改内存属性变为可执行
之后将shellcode放入,然后x32dbg里面去找到shellcode跳转过去就行
空洞开头地址-区段物理偏移
这个物理偏移可以用LoadPE看到
然后打开x32dbg找到那个区段的虚拟地址加上上面的值就可以找到shellcode
接下来的操作就一样了
就不截图了,偷懒