首页
论坛
课程
招聘
[原创]linux执行程序的Anti静态反汇编
2008-11-25 09:19 16222

[原创]linux执行程序的Anti静态反汇编

2008-11-25 09:19
16222
windows下的crack我们已经司空见惯,虽然如此。但是如我一般的菜菜们仍然前赴后继的跟着大牛们的足迹往前冲。最近对linux下的破解想了解一番,于windows下的破解不同。在linux的世界里,需要的crack的软件不是很多。当你发现一款商业linux的软件包的时候,你会很快发现,要实同样的功能的软件还有其他的开源软件。对于linux的软件的crack,仅仅依靠着对技术的追求了。而在物质的世界里。这样的追求永远没有windows下的商业利益更能够吸进人的了。
知其然,才知其所以然,再一个就是知己知彼,方能百战不殆。

最近网上搜反静态反汇编的方法,记得不是很清楚了具体内容。也懒的再去搜索了,凭大致记忆做个实验,并形成文字纪念之。。
大致有个印象说是单字节指令,与双字节指令的,干扰什么的....,我已经大致想到些什么了。动手....s

1 ,在用户名文件下建立一个空文档 test.c
在文件里写上 
#include "stdio.h"
int main()
{
char outs[]="hello word!\n";
asm volatile(            //用asm volatile是害怕Gcc 自作主张的帮我给优化了。
"jmp lab1 \n\t" 
"lab0: \n\t"
"popl %eax \n\t"
"add $1,%eax \n\t"
"jmp *%eax \n\t"
"lab1: \n\t" 
"call lab0 \n\t"
"nop");
asm volatile(
"movl $0x0d,%%edx \n\t"  // 参数三:字符串长度
"movl %0,%%ecx \n\t"  //参数二:要显示的字符串
"movl $1,%%ebx \n\t"    //参数一:文件描述符(stdout) 
"movl $4,%%eax \n\t"    //系统调用号(sys_write) 
"int  $0x80 \n\t"       //调用内核功能
                                                                 //退出程序
"movl $0,%%ebx \n\t"     //参数一:退出代码
"movl $1,%%eax \n\t"     //系统调用号(sys_exit) 
"int $0x80"         //调用内核功能
:
:"r"(outs)
:"%eax","%ebx","%ecx","%edx");     
return 0;
}



2\下面我编译它,工作目录是的test.c 的所在目录
[jun@beijihuCom ~]$ gcc -o  test.o test.c

输出了一些

运行
[jun@beijihuCom ~]$ ./test.o
hello word!

一切正常。
ok,准备工作完毕。
开始对我们的程序作手脚了。

哦,对了我们现看一下没有做手脚之前的反汇编代码。
[jun@beijihuCom ~]$ objdump -d ./test.o

翻出来的汇编不是很长很容易找到我们之前写的代码之处。

replace程序了。
gHexEdit 一个不错的十六进制的工具(当然也可以vi 修改2进制的命令是:%!xxd)
 8048391:       e8 f5 ff ff ff          call   804838b <lab0>
 8048396:       90                      nop    
 8048397:       8d 75 e7                lea    0xffffffe7(%ebp),%esi

8048396 处有俄 90 即 nop 我们要改的就是它了(实际偏移是0x396。至于为什么。以后我解释!)
直接修改为 8b 是mov 一个_ver(%ebp) 到 %ecx 中的 指令。实际可以不管他,只要是一个双元指令就可以。
ok 保存一下
检查一下我们的程序有没有坏掉,应该没有的!
[jun@beijihuCom ~]$ ./test.o
hello word!

又是一切正常。哈哈,离成功很接近
[jun@beijihuCom ~]$ objdump -d ./test.o

和刚刚的图片比较一下?


嘿嘿,不一样了吧.
看看号称能买到的最强的静态反汇编工具IDA PRO 反下看看........
l
成功欺骗...
实际上方法很简单就是利用call把下一行的地址获得,pop给%eax 加上1就是nop后的一个地址了。nop是单元指令且没有意义。现在我们把它换成二元的,静态一分析,一准错误。哈哈。

这个方法不知道在windows下能不能实现,我想应该也是可以的。但也说不准......有时间实验一下。

[注意] 招人!base上海,课程运营、市场多个坑位等你投递!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (21)
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-25 09:22
2
0
昨晚由于网络不稳定,跟帖都不能完整的发出。所以就跟感觉写了这个。感觉有点用。只不过是手动修改16进制代码,比较繁琐。以后可以想象程序怎么自实现。
雪    币: 521
活跃值: 活跃值 (119)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 活跃值 14 2008-11-25 09:46
3
0
支持~~GCC不懂
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-25 10:48
4
0
原理相通,实际上会C的稍微一看....也就不在话下了....而我也是知道点皮毛...
笨笨雄大人,能不能给个办法自实现在编译的时候直接就把 nop 那个字节改成我们需要的字节啊。
(就是说不用手动改它,而是在编译过程中,直接就插入我们想要的字节)
如果没有看上面的帖子的我举个小例子

intel 汇编

push ebp
mov ebp,esp
sub esp,40h
push NULL
push msg
push msg
push NULL
Call MessageBoxA
nop                       ;他编译后是 90h ,我的意思就是:比如我想他是 0ACh 编译后的此处就是0ACh
nop                       ;改了执行会错误,但是我们不管它。之前我是手动改,现在我想编译的时候自己生成.
.........


如果有其他高手看到此贴,方便的话也给个好的建议......
问题解决,在masm下做的试验.... 在nop处直接 "db 8bh"  ok 哈哈.......
雪    币: 243
活跃值: 活跃值 (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
amour 活跃值 2008-11-25 11:07
5
0
gcc的嵌入汇编有点恼火的说
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-25 13:49
6
0
才发现 原来这这就是传说中的花指令......

实际上我发现这种发法更本不能从根本上解决问题,因为我发现在往后面看几个字节,会发现它又恢复到原来的样子了...只是干扰了一段代码。看来这样的方法只适合在函数的入口处做干扰。这样会比较有效

又查了些资料,push ret 也可以实现,但是很多人都知道了。od调试一样可以标出来.
看来这个花指令还有点用途。至少编译成pe以后 od没有能后识别....
雪    币: 202
活跃值: 活跃值 (12)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
newjueqi 活跃值 7 2008-11-25 14:59
7
0
郁闷,不懂linux,不懂GCC,要把这些放到学习计划中
雪    币: 2058
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 活跃值 6 2008-11-25 19:41
8
0
花指令。

db 0xeb
db 0x01
db 0xZZ

这三个字节就构成了最简单的花指令,用的是0xeb,即short jmp。再复杂点,

db 0xf9
db 0x72
db 0x01
db 0xZZ

这个用的是stc,jc组合。

只上上面0xZZ不是单字节的指令,那可以使静态反汇编结果出错。

但这种花指令非常好去除,因为它没意义,直接去掉就可以。

真正复杂的是变形指令,因为不能直接去掉。
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-25 23:20
9
0
#include "stdio.h"
int main()
{
char outs[]="hello word!\n";
asm volatile(
".byte 0xeb \n\t"
".byte 0x01 \n\t"
".byte 0x22");
asm volatile(
"movl $0x0d,%%edx \n\t"  // 参数三:字符串长度
"movl %0,%%ecx \n\t"  //参数二:要显示的字符串
"movl $1,%%ebx \n\t"    //参数一:文件描述符(stdout) 
"movl $4,%%eax \n\t"    //系统调用号(sys_write) 
"int  $0x80 \n\t"       //调用内核功能
                                                                 //退出程序
"movl $0,%%ebx \n\t"     //参数一:退出代码
"movl $1,%%eax \n\t"     //系统调用号(sys_exit) 
"int $0x80"         //调用内核功能
:
:"r"(outs)
:"%eax","%ebx","%ecx","%edx");     
return 0;
}


idal 照逆不误

objdump
失败
 8048389:       eb 01                   jmp    804838c <main+0x38>
 804838b:       22 8d 75 e7 ba 0d       and    0xdbae775(%ebp),%cl
上传的附件:
雪    币: 695
活跃值: 活跃值 (55)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 活跃值 4 2008-11-26 03:31
10
0
[QUOTE=北极狐狸;541245]#include "stdio.h"
int main()
{
char outs[]="hello word!\n";
asm volatile(
".byte 0xeb \n\t"
".byte 0x01 \n\t"...[/QUOTE]

ida 是智能型递归反汇编器, gcc 线性反汇编器,所以 gcc 基本上啥都可以被欺骗
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-26 08:13
11
0
下面的花,ida 也是翻不出的。毕竟它是静态的反汇编!
"jmp lab1 \n\t" 
"lab0: \n\t"
"popl %eax \n\t"
"add $1,%eax \n\t"
"jmp *%eax \n\t"
"lab1: \n\t" 
"call lab0 \n\t"
"nop");


mik 我等你很久了,你可是答应过要写一片关于汇编和机器码关系的普及文章的....不要忘了啊.
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-26 08:18
12
0
昨天晚上没有注意看,0xZZ 是什么?我以为是0x22呢!实验的时候都是0x22忘里写的。
书呆子...给点解释啊...
雪    币: 695
活跃值: 活跃值 (55)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 活跃值 4 2008-11-26 09:12
13
0
像这种 jmp eax / call eax 以及 jmp [eax] / call [eax]
这种寄存器寻址/内存寻址的跳转,反汇编是基本是无能为力

除非,启发式反汇编,甚至更高级的模拟运算式的反汇编才有能力识别
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-26 09:40
14
0
mik 你有点避重就轻了.....
答应人的事可不要食言.......

至于启发式反汇编,或者模拟运算反汇编。是不是脱壳完全就可以不用再动态调试(做了个黄粱梦,嘿嘿)?会有这样的工具嘛?
雪    币: 695
活跃值: 活跃值 (55)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 活跃值 4 2008-11-26 09:53
16
0
我在写呀,要写得好好再贴出来呀,呵

话说,模拟运算反汇编是可以实现的,好像调试器一样,调试器将程序装入再运行一遍,然后将运行轨迹组织一下显示出来,不就行了吗。呵呵,这只是我的脑子里的构思而已
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-26 12:50
17
0
很期待啊......

那就算是动态反汇编了.......呵呵。同样也要期待这样的工具的.....
gdb就是需要先跑一边程序然后调试的时候下断点才好下。
雪    币: 695
活跃值: 活跃值 (55)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 活跃值 4 2008-11-26 13:43
18
0
写篇普及材料不算什么
我两年前写过汇编语言编译器那才值得一说。
而且是个64位的汇编语言编译器,生成64位的代码。
雪    币: 2273
活跃值: 活跃值 (22)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-11-26 14:31
19
0
哈哈哈,期待你来一个系列的普及到深入啊.............
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hugo 活跃值 2009-1-18 17:46
20
0
狐大哥好啊!!支持一吓!!
雪    币: 0
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lengyuex 活跃值 2009-10-3 14:40
21
0
楼主用AT&T汇编,牛,呵呵。
雪    币: 5003
活跃值: 活跃值 (2007)
能力值: ( LV12,RANK:220 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2014-9-23 19:33
22
0
书呆彭 变形指令是怎样的?
雪    币: 5003
活跃值: 活跃值 (2007)
能力值: ( LV12,RANK:220 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2014-9-23 19:42
23
0
楼主 你asm {}中的nop是不是应该用其他多字节的指令代替?我参考你的代码在vc6中把nop替换为_emit e8 能欺骗w32dasm
游客
登录 | 注册 方可回帖
返回