首页
社区
课程
招聘
[原创][爱琴海]2017 最新 CTF Demo 试玩版题目 ------WriteUp
发表于: 2017-7-18 19:43 5799

[原创][爱琴海]2017 最新 CTF Demo 试玩版题目 ------WriteUp

2017-7-18 19:43
5799

由于之前没搞过python的,直接百度下相关内容了解到以下两个信息

了解以上两个信息后,打开OD调试,在IDA中通过交叉引用找到GetProcessAddress后的函数地址的call调用处 


对其下断点,运行发现断不下来!!!
OD中ctrl+F2重新运行,发现了个奇怪的现象,之前的程序窗口没有被关闭,就又开了一个新进程。于是,关掉所有crackme, 打开任务管理器,重新运行cm,看到出现了两个进程

在IDA导入表中查找CrateProcess, 可以看到程序使用的是CreateProcessW, OD中使用bp CreateProcessW对其下断运行

  这里发现没有额外的命令行参数,并且在IDA中可以看到,CreateProcess之后,进程1就在WaitForSingleObject了,所以python相关的代码应该全部在进程2中执行,那么怎么调试进程2呢?     

  由于进程1没有使用调试模式来创建进程2,所以在进程2被创建成功后,使用od附加是可以成功附加的,但是这个时候附加已经过了python脚本的加载时机了,需要更早一些才行,所以我这里采用修改CC来触发异常给调试器接管。 

  考虑到GetProcessAddress之用后这些函数才正式开始使用,所以我找的是执行了GetProcessAddress函数之后的sub_403E10函数,这个函数里可以看到有Py_SetProgramName,Py_Initialize等初始化设置的函数,所以我选择在sub_403E10处修改0x56为0xCC     

  修改完成后直接运行CM,触发CC直接断在进程2的0x403E10处要设置OD为默认的实时调试器

       单步跟看到这样一个路径0022CE90 00416140 UNICODE "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\_MEI33682\base_"找过去看了下,是一些python的运行环境,并没有关键的东西,继续跟代码。

  这里添加了__main__,看来下面就快要到调用__main__函数的地方了, 继续跟代码, 就在下方不远处有一个小循环

  这个一直在查找[ebx+0x11]处等于0x73的结果,查看EBX对应的地址发现有这样一个表

  简单推测可知道开头4个字节为每一项的长度,0x11偏移处为字符串起始,0x73是s, 以s开头的有spyiboot01_bootstrap sKERNEL32.dll 

  找到一个后就去打开自身,从自身0x1F000 + offset处读取数据,解压数据,执行。最终分析的这个表的结构是|长度|偏移|大小|解压后大小|名字| 解压后的数据就是pyc,只不过被抹去了前12字节,抹去的前12字节主要的是前4字节Magic Number     
   
  打开自身

  读取padding信息(数据为压缩过的)

  解压使用的是zlib库,版本1.2.8,可根据代码中的错误提示字符串搜索得到。 

  C代码的执行的逻辑到这就结束了,因为程序运行起来看到的界面都是在python中执行的,后面就说下怎么获取并反编译pyc     

下面這包是用 python 3.4,一樣可以查表 
或是利用 archive_viewer.py 顯示前幾包的內容,開頭的 4 bytes 就是 magic number 
'EE 0C 0D 0A'    

  在sKERNEL32.dll.pyc最前面添加 EE 0C 0D 0A XX XX XX XX XX XX XX XX 十二个字节,注意是添加不是修改 我一开始是修改了开头的12字节,结果导致Easy Python Decompiler无法还原,后来在这个帖子里 
https://stackoverflow.com/questions/21067313/how-convert-and-save-python-module-from-pyobject-as-binary-data-to-use-it-lat 看到一段代码

这里减8 是因为是python2.7 只有前8字节是magic value, 而3.4是前12字节 

补上12字节的magic value后直接拖到Easy Python Decompiler就能看到python代码了,如下

  代码看起来有些问题,先注释掉while后面的用python运行下看看,注意运行环境是python3.x

  看到了这个界面,看来这就是验证的地方,仔细阅读下while循环中的代码,得知z4是输入且长度为10,z1用来验证输入的有效性, 

可知key的长度为10且由0-9,a-f组成,str(int(z4, 16))用来把输入的16进制串转为10进制串。   

  关键的判断点是if hashlib.md5(z3.encode('utf-8')).hexdigest() == b(m5, 239)     

  所以算法就是判断输入的值转10进制字符串后的md5是否与预设值相等,将b(m5, 239)放在前面直接print得到md5为524b38df7fe44db9f9b6621f14550e55

      代码中其实还有smc, 最终运行的python脚本与文件里保存的有一点区别,修改代码的函数是sub_407CC0

   这里有个有趣的事情,下面这段代码如果单步运行,那么最后不会修改python代码,直接走free,如果在这段代码之后下断点直接run过去,就会多走修改python代码的处理,经过几次单步感觉是pop ss影响了push fd的执行,noppush sspop ss就能单步跟到smc处

      smc代码

       所以最终修改后的代码应该在0x1c5处比原始的小 1 ,用比较软件打开内存dump的代码和文件中解压出来的代码可以看到确实只有此处是不同的 


上传的附件:
收藏
免费 1
支持
分享
打赏 + 5.00雪花
打赏次数 1 雪花 + 5.00
 
赞赏  CCkicker   +5.00 2017/07/20
最新回复 (8)
雪    币: 273
活跃值: (465)
能力值: ( LV15,RANK:848 )
在线值:
发帖
回帖
粉丝
2
代码好像没显示出来...
2017-7-18 19:45
0
雪    币: 1355
活跃值: (334)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
3
2017-7-18 19:54
0
雪    币: 273
活跃值: (465)
能力值: ( LV15,RANK:848 )
在线值:
发帖
回帖
粉丝
4
爱琴海 [em_63]
膜拜大神
2017-7-18 20:04
0
雪    币: 29126
活跃值: (7609)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
5
应该是424b38df7fe44db9f9b6621f14550e55啊,  这个dump结果应该是修改之前的
2017-7-18 21:26
0
雪    币: 44153
活跃值: (20210)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
6
2017-7-18 22:17
0
雪    币: 1355
活跃值: (334)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
7
风间仁 应该是424b38df7fe44db9f9b6621f14550e55啊, 这个dump结果应该是修改之前的
2017-7-19 06:24
0
雪    币: 273
活跃值: (465)
能力值: ( LV15,RANK:848 )
在线值:
发帖
回帖
粉丝
8
风间仁 应该是424b38df7fe44db9f9b6621f14550e55啊, 这个dump结果应该是修改之前的
风大神说的没错,  有smc...我是因为cmd5上两个md5给的结果是一样的,导致我没被smc坑到  ,找了下修改代码的位置,等下修改下文章
2017-7-19 09:18
0
雪    币: 1355
活跃值: (334)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
9
2017-7-19 23:46
0
游客
登录 | 注册 方可回帖
返回
//