首页
社区
课程
招聘
[原创]腾讯2010竞赛第三阶段题目思路+代码
发表于: 2010-11-19 17:24 19474

[原创]腾讯2010竞赛第三阶段题目思路+代码

2010-11-19 17:24
19474

竞赛应该以技术交流为目的,我放出这题自己做的答案和思路

这题我感觉,没有完美的答案,就像杀软一样,没有哪个能事先彻底防御最新出来的病毒木马

这题可以用以下几种方式来解决
1,debug方式
2,hook方式
3,虚拟执行的方式
4,以上几种综合

虚拟执行方式太慢了,而且环境虚拟不真实很容易被anti,我首先放弃了
hook方式要避免被检查hook
debug方式,要避免被anti

我的思路是debug方式,利用CPU的Last Branch Record,来记录程序执行的流程,用这个方式,判断出程序跳出自己镜像的地址,通过地址来找出dll的导出函数

流程大致是这样的

加载驱动,创建进程(暂停模式),把进程主线程设置单步,尝试找出进程的主模块地址和模块大小,以及第一个api的地址,然后把它们传给驱动,驱动hook int1,更改DEBUGCTLA MSR,将单步指令改成单步分支,监控程序分支流程。驱动int1捕获单步后,将From和To进行过滤,从程序主模块跳出去的才发给ring3,ring3去判断第一次api还是第二次,如果是第二次,通过api地址,找到dll模块,以及导出函数名,打印出来

优点:
1,用ring0 hook int1的方式来调试,没有使用windows的调试机制,全部自己通信,检测调试模式 无效
2,利用CPU的功能将单步指令改成了单步分支,降低调试部分代码执行次数
3,ring0过滤EIP,减少ring0 ring3通信次数
4,没用调试寄存器,检查dr0 - dr7 无效
5,ring3无任何hook,检查hook 无效
6,没有使用int3或int1断点,api代码检查 无效
6,兼容win2000 - win7(只需要cpu支持即可)

缺点:
1,无法避免单步状态检测
2,多核情况下,int1处理得不好,会出现异常(代码设置了亲和性,避免了这个问题)


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (32)
雪    币: 1155
活跃值: (4247)
能力值: ( LV5,RANK:69 )
在线值:
发帖
回帖
粉丝
2
沙发学习123
2010-11-19 17:28
0
雪    币: 179
活跃值: (26)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
学习了
2010-11-19 17:29
0
雪    币: 279
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
CPU的Last Branch Record, 头次听说, 只能膜拜
2010-11-19 17:37
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
1,无法避免单步状态检测
.................
这题还是押宝啊。。。。幸亏没单步检测。。。。
2010-11-19 17:42
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
只能膜拜 无法学习  驱动太强了
2010-11-19 17:53
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
楼主押宝太准了,学习了。
1.假设测试程序只调用系统自带dll,并且是标准调用
2.假设测试程序是单线程
3.假设外部F函数和目标函数都是由exe主程序调用
4.假设测试程序不处理单步异常
5.假设测试程序的循环量和Sleep很小
2010-11-19 18:16
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
楼主源代码里面有这么一句: by shoooo  ,难道也是马甲
2010-11-19 18:39
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
9
对于楼主的高科技的方法,我等只能膜拜
2010-11-19 18:41
0
雪    币: 7318
活跃值: (3793)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
10
1,非系统的dll一样可以检测,不信,你可以试试,api获取失败,会进入SearchAll的状态,每次都去尝试搜索第一个api的
2,多线程懒得搞了
3,题目说明里面写了, 都是由exe主程序调用的
4,这个机制问题,没法解决
5,再大也可以处理,除非程序本身运行就会超时

我只赌了2点,1,单线程,2,不检查单步

多线程可以解决的,只是懒得弄了,我觉得,测试用例有多线程会更复杂,时间误差更大(线程切换是需要时间的)
单步无法解决,所以不解决了
2010-11-19 18:45
0
雪    币: 678
活跃值: (101)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
11
学习为主要目的。
2010-11-19 18:53
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
1.
我的测试程序是这样的:(tmp.dll  和 dll.dll 是同一个文件的2个复制)
               
        LoadLibrary("tmp.dll");
        HMODULE hmod = LoadLibrary("dll.dll");
        f1 = GetProcAddress(hmod, "f1");
        f2 = GetProcAddress(hmod, "f2");

        f1();
        f2();
因为dll重定位的问题,所以程序没法检测

2.题目原话是“任意给定一个可执行程序A.exe,已知A.exe运行时会调用某外部函数F”,是说A.EXE进程在运行期间会调用到外部函数,其实并没有说明是由EXE模块来调用F函数,可能是任意一个模块或内存区域调用F函数

3.如果遇到了大规模的循环,动态运行等待目标函数的执行显然不行了

如果再赌上5个测试程序未加壳,那用静态检测就是最好的方法了。
2010-11-19 19:15
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
13
如果代码量不多,一个反汇编引擎就差不多了吧~
2010-11-19 19:48
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
14
摸顶一下    ~
2010-11-19 20:15
0
雪    币: 7318
活跃值: (3793)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
15
1,2 算我题目理解错了吧
1,我理解成测试程序只有一个bin,所以两个文件,要释放tmp.dll dll.dll,这样,我的程序是无法事先获取f1的地址,没有这个api地址,走的是SearchAll流程

3,你写一个试一试呢?
2010-11-19 20:24
0
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
16
我的比较简单,就是对系统领域的所有可执行段下断,第一次执行在系统领域就说明被调用了API
2010-11-19 20:31
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
17
不需要释放dll的。
CopyFile("c:\\windows\\system32\\kernel32.dll", "c:\\tmp.dll", 0);
这样的话事先取得的f1地址是不正确的,所以无法输出正确的结果。f1和f2函数其实应该在模块加载的时候动态取得,但是那5个测试程序都是简单的不能再简单的程序了,所以这些情况都不用考虑,考虑的人反而倒霉。
2010-11-19 20:48
0
雪    币: 7318
活跃值: (3793)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
18
你的f1是kernel32.dll里面的还是tmp.dll里面的?
如果是tmp.dll里面我是获取不到的
如果是kernel32.dll,你先把kernel32.dll卸载掉,然后在load进来?
2010-11-19 20:51
0
雪    币: 7318
活跃值: (3793)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
19
1,大家都知道这个是赌博题,大家的答案都不是完美的,只是缺陷不一样而已
2,代码发出来是以技术交流为目的的,难道大家喜欢某数字公司的竞赛,src也归主办方所有?
3,如果觉得代码有用,就学习一下,如果觉得没用,shift+del删除即可
4,如果觉得自己的答案也很不错,可以发出来,让大家学习一下
2010-11-19 20:58
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
20
我是在纳闷为什么这么好的题目配以这么烂的测试程序,题目写的神乎其神,让人有无数的想像空间,而5个测试程序却全是单一简单的程序,其中前2个程序的运行时间居然只有荒唐的10-20ms,导致产生巨大的误差。出题者到底是在考察参赛者的什么能力呢?
我个人认为这道题目的真正难点应该是考察2进制代码检测能力,即当循环时间巨大的时候,应该能够正确控制程序,分析循环内外的代码,结束循环,输出正确的结果。
例如下面的循环:
Beep();
for(__int64 i=0; i<0x1111111111111111; i++)
{
        d=c+i+b+c*234;
        e=d/4323434;
        f=e*2434232;   
}
GetTickCount();
如果不小心运行到了里面,应该及时跳出来。更复杂的情况是循环的结果影响目标函数,那就需要分析代码的功能了

Beep();
for(__int64 i=0; i<0x1111111111111111; i++)
{
        d=c+i+b+c*234;
        e=d/4323434;
        f=e*2434232;   
}
if(f%2)
GetTickCount();
else
GetCurrentProcessId();
2010-11-19 21:19
0
雪    币: 7318
活跃值: (3793)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
21
我的想象力比较丰富,我把这段代码想象成被VM掉了
2010-11-19 21:27
0
雪    币: 1262
活跃值: (775)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
22
只能膜拜,无法学习。
2010-11-20 13:41
0
雪    币: 33
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
膜拜啊,都是些没听说过的技术
2010-11-20 15:38
0
雪    币: 1098
活跃值: (193)
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
24
呵呵。不是的出题的人的水平有你和海风那么高的,或者不是出题人愿意投入的精力有你和海风那么多的。
2010-11-20 21:55
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
ReadMSR(MSR_DEBUGCTLA, &DbgCtlA);
                DbgCtlA.Lo &= ~3;
                WriteMSR(MSR_DEBUGCTLA, &DbgCtlA);
intel cpu才能用吧? ╮(╯▽╰)╭
2010-11-21 08:00
0
游客
登录 | 注册 方可回帖
返回
//