逆向分析,离不开的肯定是IDA了,在这里先几个常用的IDA快捷键。
分析程序,首先我们常规的查一下程序信息。
得到是信息是一个没有壳的64位的可执行程序,然后我们运行天津垓.exe,看看有什么特征可以寻找。
发现打开以后提示字符串Authorize:输入任意的字符后,又自动退出。
这时候,我们祭出我们的IDA去分析,因为这是一个AMD64位的架构就需要用ida64去调试分析它。
在运行的时候我们找到了字符串:Authorize
SHIFT+F12去搜索字符串
发现除了Authorize字符串以外,还有windgb,x64dbg,OD等调试器的名称,猜测程序有反调试。
此时再运行程序的时候发现程序闪退了,证实了猜测。
从字符串窗口点击来
发现EnumFunc函数对这些字符串进行了引用。
我们点进EnumFunc函数,对其逻辑进行分析
发现他获取了窗口的标题并与其字符串进行比较,如有其字符串,就把v5=1
然后我们对v5进行patcher将其变为0。
然后我们将patcher后的数据保存出去,发现左下角窗口提示成功
并且此时在运行程序并没有退出,然后便可以在字符串窗口处去分析Authorize字符串了。
IDA对不知道函数名的函数会以sub开头,我们点击第一个函数看一下。
我们看到熟悉的scanf函数,猜测scanf接受我们输入的变量,运行程序输入的值并进行了长度比较,由于我们输入的不等于18。便输出了v25的值,这里的v25因该是A jump to the sky turns to a rider kick。
经过计算长度为40的字符串数组(并且c要以0结尾),修改v25type将其改动,快捷键Y。
此时正常的显示了提示信息,然后我们便可以进入下一层循环,分析其逻辑运算
进行爆破,用Go来写脚本。
package main import "fmt" func main() { data := []int{17, 8, 6, 10, 15, 20, 42, 59, 47, 3, 47, 4, 16, 72, 62, 0, 7, 16} test := []int{0x52, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x48, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x21} //var flag string flag := "" for i := 0; i < 18; i++ { for j := 0; j < 255; j++ { t := ^(j & test[i%14]) & (j | test[i%14]) if t == data[i] { flag = flag + string(j) } } } fmt.Println(flag) }
这里也贴上Python版本的
输入关键值以后我们便发现我们进入了下一关
这时候我们会尝试去搜索Input the flag to hijack the ability of Hiden Intelligence,但我们在字符串窗口并没有见到类似的字符串,这时候我们可以用找到程序的退出点进行堆栈回溯方法去定位。
然后再IDA中定位到关键点
我们会看到一个VirtualProtect函数
如果有人c/c++ bypass AV 的时候,是不是觉得很像申请动态内存加载的函数VirtualAlloc函数呢?
这段代码的大意为是要对数据进行变动,以输入的Str作为key,让地址指向的内容与key的[i%18]进行异或。
这时候解密,我们可以用IDAPython,这里面有许多内置的函数,大家有兴趣可以研究一下。
当然这里也可以动态解密。
解密完成后,按快捷键C(code)ida便会把它识别的代码了。
此时Ida不能正常反编译,因为ida还没有把它识别一个函数,按快捷键P ,ida便把他识别为一个函数这时候便能正常的反编译了。
分析其中的逻辑,先把长度为59的字符串放到Str中,第一层循环要求Str等于51下一层循环判断也是判断值是否相等。
这时候我们便可以写一个循环去爆破这个。
package main import "fmt" func main() { data := []int{2007666, 2125764, 1909251, 2027349, 2421009, 1653372, 2047032, 2184813, 2302911, 2263545, 1909251, 2165130, 1968300, 2243862, 2066715, 2322594, 1987983, 2243862, 1869885, 2066715, 2263545, 1869885, 964467, 944784, 944784, 944784, 728271, 1869885, 2263545, 2283228, 2243862, 2184813, 2165130, 2027349, 1987983, 2243862, 1869885, 2283228, 2047032, 1909251, 2165130, 1869885, 2401326, 1987983, 2243862, 2184813, 885735, 2184813, 2165130, 1987983, 2460375} v55 := 0x8000000B for i := 0; i < 51; i++ { for j := 0; j < 256; j++ { v53 := 19683 * j % v55 if v53 == data[i] { fmt.Printf("%c", j) } } } fmt.Println() }
同样我们贴出Python版本的。
num=[2007666,2125764,1909251,2027349,2421009,1653372,2047032,2184813,2302911 ,2263545,1909251,2165130,1968300,2243862,2066715,2322594,1987983,2243862,1869885 ,2066715,2263545,1869885,964467,944784,944784,944784,728271,1869885,2263545,2283228, 2243862,2184813,2165130,2027349,1987983,2243862,1869885,2283228,2047032,1909251, 2165130,1869885,2401326,1987983,2243862,2184813,885735,2184813,2165130,1987983,2460375] flag=[] for i in range(51): for j in range(0x100): a=19683*j% 0x8000000b if a ==num[i]: flag.append(j) break print(bytearray(flag).decode())
最后爆破得出我们的flag。