作 者: loudy
使用工具: IDA6.8 (反汇编分析) python (编程解码) OD (动态调试)
步 骤:
一、定位关键代码
该程序有加壳,但对主要流程影响不大,难点在于分析luajit 代码,定位主要流程。只要流程清晰了,该题没有难度,只是简单异或运算。
(1 )脱壳
其实也不算真正脱壳,其实就是等程序运行起来后,dump 内存镜像。
这样在IDA 中可以分析解密后的函数和解密后的字符串,如下图
(2 )定位关键点
从IDA 的字符串窗口可以看到该程序使用了LuaJIT 2.1.0-beta3 且Lua 版本号为Lua 5.1 。
通过“main” (调用Lua 的main 函数)关键字在IDA 中定位到如下位置。
其上面从0040103D 开始的一大段mov 指令实际是在栈中生成了一个luajit 的bytecode 。
二、解密
通过OD 动态加载后,通过识别luajit 文件头{0x1b ,0x4c ,0x4a} 提取出该文件。
接下来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漏洞挖掘与利用;代码审计。
上传的附件: