-
-
[原创]KCTF2021秋季赛第9题 万事俱备
-
2021-12-9 02:34 18137
-
E语言,IDA+E-Decompiler,定位关键函数sub_4010CB
里面会释放7z.exe和ctf.7z,而后用7z.exe去解压ctf.7z,得到python27.exe和check.py,最后调用python27.exe check.py
校验逻辑全部在check.py中,发现是字节码
运行python27.exe,重命名为check.pyc,import一下,然后dir看有哪些东西
可以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 50 51 52 53 54 55 56 57 | import check #input ''' 05C1930A146B0FC3 8E6E67F357338CC7912F3161CBAC4273 ''' from check import * def funcA(A,B): print ( "A-----------GO" ) print (A,B) ret = O00(A,B) #print(ret) print (A,B) print ( "A----------END" ) return ret def funcB(A,B,C): print ( "B-----------GO" ) print (A,B,C) print (A.encode( 'hex' )) ret = O00OooOOo0O(A,B,C) print (ret.encode( 'hex' )) print ( "B----------END" ) return ret def funcC(A,B): print ( "C-----------GO" ) print (A,B) ret = OO0oo0(A,B) print (ret) print ( "C----------END" ) return ret def funcD(A,B): print ( "D-----------GO" ) print (A,B) ret = o00oo0(A,B) print (ret) print ( "D----------END" ) return ret def funcE(A,B): print ( "E-----------GO" ) print (A,B) ret = oOO0o00Oo(A,B) #print(ret) print ( "E----------END" ) return ret check.O00 = funcA check.O00OooOOo0O = funcB check.OO0oo0 = funcC check.o00oo0 = funcD check.oOO0o00Oo = funcE check.O0ooo0() |
算法上半,猜测是个RC4,求出最后的xor就可
得到xor key 1b4ff4d1f9f35895b40aeca5539cba0a
算法下半,验证猜出D函数是个rot,需要调试python27.exe
下断所有的PyNumber,PyInt,PyLong类函数,只调用B函数减少干扰,根据程序运行,做好log输出信息,参考https://docs.python.org/2.7/c-api/number.html了解api参数等
下条件断点PyInt_FromLong,rcx==数字(这里下断了0xf188),ret时会创建一个Python对象,偏移量0x10是这个数字,硬件断点跟踪,可以追踪对这个数字执行的逻辑,理论上可以还原算法
结果群里有人 hint
也做过今年春季赛第7题,感觉很像,只是改了下数字顺序,按照现在已经逆向出的算法,求数组输入顺序
拿出以前的脚本改改了
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include<stdio.h> #define int unsigned int int rol( int num, int i){ return (num << (i % 16 ) | num >> (( 16 - i) % 16 ))& 0xffff ; } int ror( int num, int i){ return (num >> (i % 16 ) | num << (( 16 - i) % 16 ))& 0xffff ; } void dec(unsigned short * a, int r,unsigned short * p){ int t[ 110 ]; int x1 = p[ 0 ]^p[ 1 ]; / / a[ 4 ]^a[ 5 ] int x2 = p[ 2 ] + p[ 3 ]; / / a[ 2 ] + a[ 3 ] int x3 = p[ 4 ] - p[ 5 ]; / / a[ 1 ] - a[ 0 ] int x4 = rol(p[ 6 ]^p[ 7 ],r); / / a[ 6 ]^a[ 7 ] t[ 1 ] = x2; t[ 2 ] = x1; t[ 3 ] = x3& 0xffff ; t[ 4 ] = t[ 1 ]&t[ 2 ]; t[ 0 ] = ~t[ 2 ]& 0xffff ; t[ 5 ] = t[ 0 ]&t[ 3 ]; t[ 12 ] = t[ 4 ]|t[ 5 ]; t[ 6 ] = (t[ 12 ]& 0XFFFF ) * t[ 2 ]; t[ 7 ] = t[ 6 ]>>r; t[ 8 ] = t[ 7 ] + 0X18 ; t[ 9 ] = t[ 3 ] ^ (t[ 8 ] & 0XFFFF ); t[ 10 ] = t[ 8 ]&t[ 12 ]; t[ 11 ] = t[ 9 ]|t[ 10 ]; a[ 0 ] = p[ 5 ] - t[ 8 ]; a[ 1 ] = x3 + a[ 0 ]; a[ 2 ] = p[ 3 ] + t[ 9 ]; a[ 3 ] = p[ 2 ] - t[ 9 ]; a[ 4 ] = p[ 1 ]^t[ 11 ]^ 0X0000 ; a[ 5 ] = p[ 0 ]^t[ 11 ]^ 0X0000 ; a[ 6 ] = ror(p[ 7 ],r)^t[ 12 ]; a[ 7 ] = ror(p[ 6 ],r)^t[ 12 ]; #if 0 for ( int i = 0 ;i< 13 ;i + + ){ printf( "%.8x " ,t[i]); } printf( "\n" ); #endif } int main(){ for ( int x = 0 ;x< 16 ;x + + ){ unsigned char p1[ 16 ] = { 0 }; unsigned char t[ 16 ] = { 0 }; / / char s[ 16 ] = { 0x4b , 0x43 , 0x54 , 0x46 , 0x00 , 0x0a , 0x09 , 0x08 , 0x07 , 0x06 , 0x05 , 0x04 , 0x03 , 0x02 , 0x11 , 0x10 }; char * s = "KCTF@021GoodLuck" ; unsigned short r[ 8 ] = { 0 }; unsigned short s2[ 8 ] = { 0 }; printf( "%.1x::" ,x); for ( int i = 0 ;i< 8 ;i + + ){ s2[i] = s[ 2 * i + 0 ] + s[ 2 * i + 1 ] * 256 ; } dec(r,x,s2); for ( int i = 0 ;i< 8 ;i + + ){ t[ 2 * i + 0 ] = r[i] % 256 ; t[ 2 * i + 1 ] = r[i]>> 8 ; } / / 4546 4330 3733 3530 4132 4445 4530 3333 / / for ( int i = 0 ;i< 8 ;i + + ){ / / p1[ 2 * i + 0 ] = t[( 6 - i * 2 ) % 16 ]; / / p1[ 2 * i + 1 ] = t[( 5 - i * 2 ) % 16 ]; / / } int shuffle[] = { 2 , 1 , 4 , 3 , 6 , 5 , 0 , 7 }; for ( int i = 0 ;i< 8 ;i + + ){ printf( "%.2X" ,t[shuffle[i] * 2 ]); printf( "%.2X" ,t[shuffle[i] * 2 + 1 ]); } printf( "\n" ); } } |
寻找最后比较的输出,提供的注册码是直接比较了username,猜测KCTF用00补全,没猜对,只好测一下
username输入KCTF,serial用提供的,
CheatEngine搜索提供的username
找到应该比较的字符串是KCTF@021GoodLuck
算法爆破会有16个结果,输进去观察发现rot中参数是9,使用第9个结果 B645EB508058BC1B67BA9F5D1346E8AD
B645EB508058BC1B67BA9F5D1346E8AD和之前的key xor
得到AD0A1F8179ABE48ED3B073F840DA52A7,即为正确答案
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界