常见魔改UPX

几篇大佬的文章:
https://cujo.com/blog/upx-anti-unpacking-techniques-in-iot-malware/
https://www.cnblogs.com/ichunqiu/p/7245329.html
https://bbs.kanxue.com/thread-275753.htm
https://www.52pojie.cn/forum.php?mod=viewthread&tid=326995

Header Structures

img
img
img

p_filesize

  1. 图一的p_filesize可以全部修改成0(图三也有p_filesize)

  2. example [susctf mirai]
    可以看到p_info中的p_filesize为0(addr:0x00F4)
    img

    找到第二段p_size位置有值,将0x2878的值放到0x00F4处即可-d解密.
    img

overlay_offset

  1. overlay_offset位于文件尾部,是p_info的偏移值,当修改overlay_offset时直接-d会报错l_info(逆天,我感觉是p_info来着)

  2. example [basectf UPX PRO]
    直接打开overlay_offset是
    img

    找到p_info的位置,为0xF4
    img
    将overlay_offset改为0xF4即可直接-d解密.

magic on linux

  1. linux也可以魔改upx!,将FUK?改为UPX!即可
    img

手脱upx on linux

  1. upx加壳后很多时候会导致exe变为dyn类型,欺骗ida进行调试的方法如下:
    • 将原程序用010改为exe,用ida打开该程序.
    • 在debuger option中选择调试原程序(dyn).
  2. 在此处下读写断点
    img
  3. 调式,大概第三次断下来的时候,在rdi中有下面的情况
    img
  4. 将qword_45B0E8数组未定义一下,得到下面结果
    img
  5. 进入unk_45C080,下执行断点,并取消第一次下的断点,执行,断下的结果的形式不止一种,仅作参考
    img
  6. 执行dump_elf.py,终端输入dump_elf(base_addr),即可得到dump.bin文件.
  7. dump_elf已知问题解决: 见实例

实例:encsh程序(自改UPX+反调试)

  1. upx加壳后很多时候会导致exe变为dyn类型,欺骗ida进行调试的方法如下:

    • 将原程序用010改为exe,用ida打开该程序.
    • 在debuger option中选择调试原程序(dyn).
  2. 因为运行发现有反调试,调用strace查看是否有调用ptrace()

     strace ./encsh
    
  3. 确定存在后,可以用pwndbg确认位置.并且由于反调试在upx解压缩的过程中,需要先等upx自己mmap出来prace()的内存

     gdb encsh
     catch syscall mprotect
     catch syscall ptrace
     vmmap       //确定base_addr
     r           //运行到断点
     c           //continue
    
    • 之后找到mprotect的地址,在他后面下断点,之后运行到此位置后就可以进入ptrace()的地址,之后c出来syscall的代码,下断点rax == 0x65,之后运行,将rax置0,即可绕过反调试
      • mprotect的地址是动态的
      • ptrace()的地址不是....
      • .....我也不知道为什么
    • 之后在入口点下断点,run,之后确定循环解压位置(只看write的部分,32位一直写,等到出现一个确定的地址,而64位好像是以偏移显示),等走出循环,回到入口点,即可进入OEP,在此处下执行断点,将入口点的断点disable,再次断住,就是OEP,之后运行脚本dump_elf
  4. 得到dump.bin后,放入ida,找到ELF Dynamic Information,将此处代码u掉,之后运行脚本,将大于原先base_addr的部分减去原base_addr(脚本已经修复此处)

  5. 对于.got.plt section的部分需要手动清零,对应位置如下(或者直接找到.got节也可以)

    • 需要修的程序对应的位置(貌似是start函数的最后一个参数):

      img

    • 正常程序对应的位置:

      img

    • 将下面两处值清零:

      img

posted @ 2024-10-11 18:09  Un1corn  阅读(396)  评论(0)    收藏  举报