-
-
[原创]2022KCTF春季赛 第八题 迷雾散去
-
2022-5-28 02:26 8545
-
程序用了ptrace,防止调试程序,这样IDA,CheatEngine都是用不了的,不过还是可以用scanmem(https://github.com/scanmem/scanmem)读取内存查看内存信息(需要自行编译+改部分代码,此处略过)
程序最后会有 "顺利通关" 字样,找到相关内存并dump
dump出附近内存,用作对比,没啥想法
ida查算法特征,发现有个des,算法和上次比赛的代码差不多,可以hook
frida hook后发现没有输出,写个debugger发现程序停住,说明frida hook代码还是执行了的,可以将信息输出到文件里
部分代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | mylogfile = new File ( "/data/data/a.b.c/d1.txt" , "wb" ); Interceptor.attach(baseAddr.add( 0x4d15 ),{ onEnter:function(args){ var mylog = ""; mylog + = "DES Enc:" + (this.context as any ).lr.sub(baseAddr) + "\n" ; / / mylog + = JSON.stringify(this.context) + "\n" ; / / mylog + = (this.context as any ).lr.sub(baseAddr) + "\n" ; / / / / mylog + = hexdump(args[ 0 ],{ / / / / offset: 0 , / / / / length: 0x100 , / / / / header:true, / / / / ansi:true / / / / }) / / / / mylog + = "\n" ; / / mylog + = hexdump(args[ 1 ],{ / / offset: 0 , / / length: 0x10 , / / header:true, / / ansi:true / / }) / / mylog + = "\n" ; / / mylog + = hexdump(args[ 2 ],{ / / offset: 0 , / / length: 0x10 , / / header:true, / / ansi:true / / }) / / mylog + = "\n" ; mylogfile.write(mylog); mylogfile.flush(); },onLeave:function(ret){ var mylog = ""; mylog + = "After DES Enc:" + (this.context as any ).lr.sub(baseAddr) + "\n" ; / / mylog + = JSON.stringify(this.context) + "\n" ; / / mylog + = hexdump((this.context as any ).r2,{ / / offset: 0 , / / length: 0x10 , / / header:true, / / ansi:true / / }) / / mylog + = "\n" ; mylogfile.write(mylog); mylogfile.flush(); count + = 1 if (count = = 2 ){ / / debugger; } } }); |
找出返回地址0xe409,观察发现vmp代码有点相似结构 44 f0 0d e5 ? ? 00 ea,ghidra强制识别这些arm代码试试
1 2 3 4 5 6 7 8 | f = open ( "libcrackme.so" , "rb" ) data = f.read() f.close() result = 0 while (result ! = - 1 ): result = data.find(bytearray.fromhex( "44 F0 0D E5" ),result + 4 ) print ( hex (result + 0x1000 )) |
hook字符串函数,得到最后输出字符串位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | function hookart(){ var baseAddr = Module.findBaseAddress( "/apex/com.android.runtime/lib/libart.so" ); / / var baseAddr = Module.findExportByName(null, "_ZN3art12_GLOBAL__N_18CheckJNI12NewStringUTFEP7_JNIEnvPKc" ); console.log( "Art" ,baseAddr) Interceptor.attach(baseAddr.add( 0x2C85D1 ), { onEnter: function (args) { if (args[ 1 ].readCString() = = "您输错了" || args[ 1 ].readCString() = = "顺利过关" ){ console.log(args[ 1 ].readCString(),args[ 1 ]); var mainAddr = Module.findBaseAddress( "libcrackme.so" ); console.log((this.context as any ).lr.sub(mainAddr)); for (var i = 0 ;i< 64 ;i + + ){ / / console.log((this.context as any ).sp.add(i * 4 ).readPointer(),(this.context as any ).sp.add(i * 4 ).readPointer().sub(mainAddr)); } console.log(hexdump(args[ 1 ].add( 0xe0 ),{ offset: 0 , length: 128 , header:true, ansi:true })); console.log(JSON.stringify(this.context)); console.log(hexdump(this.context.sp.sub( 0 ),{ offset: 0 , length: 128 , header:true, ansi:true })); memset_log = false; mylogfile.close(); / / debugger; } }, onLeave: function (ret) { } } ); } |
计算下最后输出字符串位置返回是14664
去hook vmp函数找一下,hook后再运行会崩溃,不过能输出寄存器信息,也能暂停程序留出dump内存的机会
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | Interceptor.attach(baseAddr.add( 0xf628 ),{ onEnter:function(args){ if (true || (this.context as any ).sp.sub( 0x44 ).readPointer().sub(baseAddr) = = ptr( 0x145e8 )){ var mylog = ""; mylog + = (this.context as any ).sp.sub( 0x44 ).readPointer().sub(baseAddr) + " Result " + (this.context as any ).lr.sub(baseAddr) + "\n" ; mylog + = JSON.stringify(this.context) + "\n" ; / / mylog + = hexdump((this.context as any ).r3,{ / / offset: 0 , / / length:(this.context as any ).r0.sub((this.context as any ).r3).toUInt32(), / / header:true, / / ansi:true / / }) mylog + = "\n" ; console.warn( "!! " ,JSON.stringify(this.context)) mylogfile.write(mylog); mylogfile.flush(); debugger; } },onLeave:function(ret){ } }); |
附近hook函数找了一下,没有找到判定条件,不过能确定正确输入会有0xc,不正确的输入则是0x0
去跟des算法,发现是加密用户名的,和序列号没啥关系,发现走到后面,程序没有断下
发现1e48c 跳转到xref较少的地方
一个个试,发现找到一个地方正好是卡在des加密后,得出判断结果前,且正好有返回结果为0xc
观察也可以发现有个循环结构,多次尝试hook输出信息,根据寄存器信息和dump出的内存猜出xor
KCTF对应序列号为3432354538383237303738384143323436323438463944343043393831364643
[招生]科锐逆向工程师培训46期预科班将于 2023年02月09日 正式开班