查看: 123|回复: 0

[Reverse] Linux逆向之加壳&脱壳

[复制链接]
发表于 2020-6-3 21:07:40 | 显示全部楼层 |阅读模式
  Linux中比较常见的壳是UPX,常用这个开源软件进行一键upx加壳和脱壳
  这里做一个简单演示
#include <stdio.h>
void fun1()
{
puts("fun1:hello,world!");
sleep(1);
}
void fun2()
{
puts("fun2:hello,world!");
sleep(1);
}

int main(int argc, char const *argv[])
{
puts("main:hello,world!");
fun1();
fun2();

return 0;
}

  gcc ./test.c -o test --static
  得到一个静态编译的test可执行文件,这里之所以要用静态编译,是因为upx加壳需要使得文件大小大于40kb,否则没办法进行加壳压缩

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  这里可以看到upx的用法,一般来说./upx test,即可快速把test加壳并且直接修改test源文件
  如果加上-d参数表示进行脱壳,参数-1 ~ -9表示压缩的等级,1为最低级压缩同时也是最快的,而9表示最高等级压缩同时比较耗时,参数-k则表示保留原程序的备份
  upx加壳之后可以看到程序能正常运行

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  加壳到底改变了源程序的哪些东西?
  可以通过readelf –hlS --w test来查看elf文件在加壳前的情况

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  而加壳后:

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  对比发现,upx压缩之后的elf头部信息,段表信息全都发生了变化,把大量的有关elf的信息全部去除了,只留下一个upx壳自定义的程序入口执行地址
  但这种加壳毕竟是直接用工具一键加壳的,同样的用该工具很容易就能被脱壳,并且很容易被发现是upx壳

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  可以看到,这里用checksec和strings都能轻易识别出upx的壳
  因此为了让upx加壳过的程序没那么轻易被识别,我们把程序扔进010editor里面进行修改,把相关字符串和UPX关键词都给patch掉,然后再来康康

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  这时会发现,不但检测不到是upx壳,而且upx也没办法进行脱壳
  这时就需要我们进行手动脱壳了,加壳的本质就是把原来的程序的数据全部压缩加密了,在静态文件中无法分析,随着程序的执行,运行时会将代码释放到内存中
  我这里用的方法是用ida远程调试test程序,找到upx自解壳后的 OEP,再把内存给dump出来,就可以实现手动脱壳了
  首先ida远程连接Ubuntu的中的test需要一个 linux_server64 远程服务器,这个在ida目录的dbgsrv文件夹下就有
  将其复制到Ubuntu中,然后运行它
  接着来到ida端,选择调试器:Remote Linux Debugger

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  以上的文件路径和ip地址均为远程端中的
  设置完成后在start函数中下个断点,然后开始调试

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  进入调试界面后,可以看到程序的运行情况

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  然后一路f8步过执行,其中会遇到很多跳转循环,根据向下执行的原则不断跳过循环,最后来到这里jmp r13

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  会jmp到另外一个段上面去,这个段的名称这里显示的是test,这是因为这个段经过前面的mmap,mprotect等系统调用自己生成的一个段空间地址

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  到了这个新的段以后,遇到第一个call的时候就f7进入,然后继续f8一点点走下去

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  走到这的时候会发现有三个向上循环执行的语句,仍然按照向下跳过执行的方式去跳过这三个循环

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  跳过了这三个循环,就可以一路f8,最后会来到一个jmp语句,这里即将回到OEP,f7一下

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  继续f7

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  可以看到,执行的地址又回到了0x400890,这其实就是最开始未进行加壳的程序的起始函数 __start
  他的第一个参数rdi指向的正是main函数

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  这个时候我们就找到了OEP了,可以通过ida加载idc脚本的方式把当前的内存给dump出来
  脚本如下
#include <idc.idc>
#define PT_LOAD              1
#define PT_DYNAMIC           2
static main(void)
{
auto ImageBase,StartImg,EndImg;
auto e_phoff;
auto e_phnum,p_offset;
auto i,dumpfile;
ImageBase=0x400000;
StartImg=0x400000;
EndImg=0x0;
if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f )
{
if(dumpfile=fopen("dumpfile","wb"))
{
e_phoff=ImageBase+Qword(ImageBase+0x20);
Message("e_phoff = 0x%x\n", e_phoff);
e_phnum=Word(ImageBase+0x38);
Message("e_phnum = 0x%x\n", e_phnum);
for(i=0;i<e_phnum;i++)
{
if (Dword(e_phoff)==PT_LOAD || Dword(e_phoff)==PT_DYNAMIC)
{
p_offset=Qword(e_phoff+0x8);
StartImg=Qword(e_phoff+0x10);
EndImg=StartImg+Qword(e_phoff+0x28);
Message("start = 0x%x, end = 0x%x, offset = 0x%x\n", StartImg, EndImg, p_offset);
dump(dumpfile,StartImg,EndImg,p_offset);
Message("dump segment %d ok.\n",i);
}
e_phoff=e_phoff+0x38;
}

fseek(dumpfile,0x3c,0);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);

fseek(dumpfile,0x28,0);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);
fputc(0x00,dumpfile);

fclose(dumpfile);
}else Message("dump err.");
}
}
static dump(dumpfile,startimg,endimg,offset)
{
auto i;
auto size;
size=endimg-startimg;
fseek(dumpfile,offset,0);
for ( i=0; i < size; i=i+1 )
{
fputc(Byte(startimg+i),dumpfile);
}
}

  执行完这个脚本后,用ida打开dumpfile,可以发现能够清楚的看清整个程序的反编译逻辑

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  复制回Ubuntu运行也仍然没有问题

Linux逆向之加壳&脱壳

Linux逆向之加壳&脱壳
  有兴趣的研究一下upx实现源码的,可以康康下面的链接
参考链接  https://github.com/upx/upx
https://bbs.pediy.com/thread-255519.htm
  源码分析相关:
https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=19345


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046
微信公众号
快速回复 返回顶部 返回列表