首页
社区
课程
招聘
[原创]看雪CTF2017第十五题简单解析
2017-7-1 08:05 5756

[原创]看雪CTF2017第十五题简单解析

loudy 活跃值
10
2017-7-1 08:05
5756

    者:loudy

使用工具:IDA6.8(反汇编分析) python(编程解码) OD(动态调试)

    骤:

一、定位关键代码

该程序有加壳,但对主要流程影响不大,难点在于分析luajit代码,定位主要流程。只要流程清晰了,该题没有难度,只是简单异或运算。

1)脱壳

其实也不算真正脱壳,其实就是等程序运行起来后,dump内存镜像。

这样在IDA中可以分析解密后的函数和解密后的字符串,如下图

2)定位关键点

IDA的字符串窗口可以看到该程序使用了LuaJIT 2.1.0-beta3 Lua版本号为Lua 5.1

通过“main”(调用Luamain函数)关键字在IDA中定位到如下位置。

其上面从0040103D开始的一大段mov指令实际是在栈中生成了一个luajitbytecode

二、解密

   通过OD动态加载后,通过识别luajit文件头{0x1b0x4c0x4a}提取出该文件。

接下来Google找到luajit-decomp项目源码和LuaJIT-2.1.0-beta3源码,编译luajit,替换luajit-decomp中的对应文件,对提取出的luajit反编译,得到如下结果。

function randomFunction by (INPUT_VAR_0_,INPUT_VAR_1_)
     var_0_4 = INPUT_VAR_0_
     var_0_5 = INPUT_VAR_1_
     var_0_6 = INPUT_VAR_1_
     string.byte( string.sub(var_0_4, var_0_5, var_0_6) )
end
 
function randomFunction main (INPUT_VAR_0_)
     var_1_2 = INPUT_VAR_0_
     var_1_1 = string.len(var_1_2)
     if var_1_1 ~= 0 then
         --jump to 0009 (if previous if statement is false) --0009 JMP-JMP
         var_1_1 = 0 --var_1_1 NUMBER-NUMBER
         return var_1_1
     end
     var_1_3 = INPUT_VAR_0_                                      key[0]
     var_1_4 = 1 --var_1_4 NUMBER-NUMBER  
     var_1_2 = by(var_1_3, var_1_4)                     key[1]
     var_1_3 = 112 --var_1_3 NUMBER-NUMBER  
     var_1_1 = bit.bxor(var_1_2, var_1_3)      key[1]^112
     var_1_4 = INPUT_VAR_0_
     var_1_5 = 2 --var_1_5 NUMBER-NUMBER
     var_1_3 = by(var_1_4, var_1_5)                     key[2]
     var_1_4 = 101 --var_1_4 NUMBER-NUMBER
     var_1_2 = bit.bxor(var_1_3, var_1_4)      key[2]^101
     var_1_5 = INPUT_VAR_0_
     var_1_6 = 3 --var_1_6 NUMBER-NUMBER
     var_1_4 = by(var_1_5, var_1_6)                     key[3]
     var_1_5 = 100 --var_1_5 NUMBER-NUMBER
     var_1_3 = bit.bxor(var_1_4, var_1_5)      key[3]^100
     var_1_6 = INPUT_VAR_0_
     var_1_7 = 4 --var_1_7 NUMBER-NUMBER
     var_1_5 = by(var_1_6, var_1_7)                     key[4]
     var_1_6 = 105 --var_1_6 NUMBER-NUMBER
     var_1_4 = bit.bxor(var_1_5, var_1_6)      key[4]^105
     var_1_7 = INPUT_VAR_0_
     var_1_8 = 5 --var_1_8 NUMBER-NUMBER
     var_1_6 = by(var_1_7, var_1_8)                     key[5]
     var_1_7 = 121 --var_1_7 NUMBER-NUMBER     
     var_1_5 = bit.bxor(var_1_6, var_1_7)      key[5]^121
     var_1_8 = INPUT_VAR_0_
     var_1_9 = 6 --var_1_9 NUMBER-NUMBER
     var_1_7 = by(var_1_8, var_1_9)                     key[6]
     var_1_8 = 49 --var_1_8 NUMBER-NUMBER
     var_1_6 = bit.bxor(var_1_7, var_1_8)      key[6]^49
     var_1_9 = INPUT_VAR_0_
     var_1_10 = 7 --var_1_10 NUMBER-NUMBER
     var_1_8 = by(var_1_9, var_1_10)                    key[7]
     var_1_9 = 50 --var_1_9 NUMBER-NUMBER
     var_1_7 = bit.bxor(var_1_8, var_1_9)      key[7]^50
     var_1_10 = INPUT_VAR_0_
     var_1_11 = 8 --var_1_11 NUMBER-NUMBER 
     var_1_9 = by(var_1_10, var_1_11)               key[8]
     var_1_10 = 51 --var_1_10 NUMBER-NUMBER
     var_1_8 = bit.bxor(var_1_9, var_1_10)     key[8]^51
     var_1_11 = INPUT_VAR_0_
     var_1_12 = 9 --var_1_12 NUMBER-NUMBER
     var_1_10 = by(var_1_11, var_1_12)                  key[9]
     var_1_11 = 52 --var_1_11 NUMBER-NUMBER
     var_1_9 = bit.bxor(var_1_10, var_1_11)    key[9]^52
     var_1_12 = INPUT_VAR_0_
     var_1_13 = 10 --var_1_13 NUMBER-NUMBER
     var_1_11 = by(var_1_12, var_1_13)                  key[10]
     var_1_12 = 53 --var_1_12 NUMBER-NUMBER
     var_1_10 = bit.bxor(var_1_11, var_1_12)   key[10]^53
     var_1_13 = INPUT_VAR_0_
     var_1_14 = 11 --var_1_14 NUMBER-NUMBER
     var_1_12 = by(var_1_13, var_1_14)                  key[11]
     var_1_13 = 54 --var_1_13 NUMBER-NUMBER
     var_1_11 = bit.bxor(var_1_12, var_1_13)   key[11]^54
     var_1_14 = INPUT_VAR_0_
     var_1_15 = 12 --var_1_15 NUMBER-NUMBER
     var_1_13 = by(var_1_14, var_1_15)                  key[12]
     var_1_14 = 55 --var_1_14 NUMBER-NUMBER
     var_1_12 = bit.bxor(var_1_13, var_1_14)   key[12]^55
     var_1_13 = var_1_1
     var_1_14 = var_1_2
     var_1_15 = var_1_3
     var_1_16 = var_1_4
     var_1_17 = var_1_5
     var_1_18 = var_1_6
     var_1_19 = var_1_7
     var_1_20 = var_1_8
     var_1_21 = var_1_9
     var_1_22 = var_1_10
     var_1_23 = var_1_11
     var_1_24 = var_1_12
     return var_1_13, var_1_14, var_1_15, var_1_16, var_1_17, var_1_18, var_1_19, var_1_20, var_1_21, var_1_22, var_1_23, var_1_24
end
 
function someFunc2()
     require("bit")
     local randomFunction0 = function() end -- starts at  test.lua:0
     by = randomFunction0
     local randomFunction1 = function() end -- starts at  test.lua:0
     main = randomFunction1
     return
end

我们主要关注其中的main函数,上面已经用c语法注释出来。其实就是对输入分别与下面这一串异或,返回结果。

[112,101,100,105,121,49,50,51,52,53,54,55]

接下来0040222C处的代码取得lua输出的每一个值分别与下面这一串值异或。

[0x5,0x12,0xa,0x29,0x42,0x41,0x75,0x61,0x35,0x83,0x55,0x94]

接下来004022F0处,异或后的值分别与下面着串值比较,相等则注册成功。

[0x18,0x16,0x1e,0x2f,0x48,0x11,0x21,0x37,0x33,0x86,0x52,0x94]

那么python编写如下代码,即可得到真正注册码“maposafe2017”

a = '000000000000'
b = [112,101,100,105,121,49,50,51,52,53,54,55]
c = [0x5,0x12,0xa,0x29,0x42,0x41,0x75,0x61,0x35,0x83,0x55,0x94]
d = [0x18,0x16,0x1e,0x2f,0x48,0x11,0x21,0x37,0x33,0x86,0x52,0x94]
al = len(a)
a1 = list(a)
for i in range(al):
    a1[i] = chr(b[i]^c[i]^d[i])
print ''.join(a1)

全文完,注册码“maposafe2017”



[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (1)
雪    币: 910
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
自强zq 2019-10-23 17:33
2
0
感谢
游客
登录 | 注册 方可回帖
返回