题目链接:https://pan.baidu.com/s/1whGqn75JvrO82XpIc2TyMg
提取码:q3nl
首先程序对输入的数据构建二叉树,节点的结构体:
程序使用递归的方式构建二叉树,比节点大的数据作为右孩子,比节点小的数据作为左孩子,构建完成后如果中序遍历二叉树,升序排列。
接着sub_4017DD函数对二叉树进行先序遍历。
接着将遍历节点值存放的数组传进sub_401D6E函数中。
接着分析sub_401D6E函数。
sub_4018F0是DES加密,密钥可以找到是"fa1conn",DES加密过程:明文64位->初始置换IP->轮加密变换->逆初始变换IP-1->密文。可以根据初始置换IP,初始逆置换IP-1,选择置换PC-1,选择置换PC-2四个常量表,以及16加密变换的for循环来识别是DES加密。
sub_40195A里面是一个三重循环,是将DES加密后的前36个数据与dword_408020数组存的36个数据当矩阵相乘得到一个6*6的矩阵。
sub_401A24是将得到的矩阵数据与dword_40B6D0数组中的数据比较,比较完矩阵的36位数据后,再比较DES加密后的最后四位的值。
这样我们就可以用python写出脚本进行矩阵逆运算,再进行DES解密,运行即可得到先序遍历的结果"LC-+)=1234[email protected]{the^VYXZfislrvxyz}"。
from numpy import * from Crypto.Cipher import DES A = [[0x17, 0x41, 0x18, 0x4E, 0x2B, 0x38], [0x3B, 0x43, 0x15, 0x2B, 0x2D, 0x4C], [0x17, 0x36, 0x4C, 0x0C, 0x41, 0x2B], [0x59, 0x28, 0x20, 0x43, 0x49, 0x39], [0x17, 0x2D, 0x1F, 0x36, 0x1F, 0x34], [0x0D, 0x18, 0x36, 0x41, 0x22, 0x18]] mA = matrix(A) B = [[0x0AA92, 0x0C006, 0x0A815, 0x0C920, 0x0D095, 0x0CAD1], [0x7004, 0x9B3C, 0x68A1, 0x0A2C1, 0x8B5B, 0x9EB5], [0x7E37, 0x7AA2, 0x4F95, 0x0A344, 0x82AC, 0x8C00], [0x432B, 0x71F7, 0x732D, 0x6E76, 0x70A1, 0x6F34], [0x0B465, 0x0E401, 0x0AF37, 0x0DAD2, 0x0DF89, 0x0ECFA], [0x657D, 0x6838, 0x5FCE, 0x977C, 0x71F4, 0x759E]] mB = matrix(B) mX = mB * mA.I X = matrix.tolist(mX) cipher = ‘‘ for i in range(6): for j in range(6): X[i][j] = int(round(X[i][j])) cipher += hex(X[i][j])[2:].zfill(2) cipher += ‘733CF57C‘ cipher = cipher.decode(‘hex‘) key = ‘fa1conn\x00‘ des = DES.new(key, DES.MODE_ECB) plain = des.decrypt(cipher) print(plain)
接着sub_401ACC确认flag前十八位的值,恢复后得到flag前十八位为”LCTF{this-RevlrSE=“
str = "LC-+)[email protected]{the^VYXZfislrvxyz}" arr = [0,1,14,12,17,18,19,27,28,2,15,20,31,29,30,16,13,5] for i in arr: print(str[i],end="")
接着又对二叉树进行后序遍历,然后调用sub_4021DE函数。
分析sub_4021DE函数。
sub_401D90函数中将flag中每个字符的ascii值的和作为srand()的种子,然后将401E79地址开始的值与rand()异或。
但是不能直接对程序的401E79处的值写脚本进行解密。
因为需要注意的是这只是第二段smc,在开始的时候是存在反调试的,并且反调试和第一段smc有关。也就是说两段smc正确处理后,才能得到正确的自解密函数。
我们选择patch掉程序中进程名,然后运行程序让第一段smc正确解密,我们当前程序从dump下来得到正确的第一段smc数据,然后写IDApython解密smc函数。
#rand()值 arr = [0x9B,0xBC,0x70,0x3A,0x99,0xF4,0x68,0xB0,0x5F,0x6F,0xDB,0xF1,0xD,0x53,0xA0,0x8C,0xC5,0xCE,0x83,0x25,0x6D,0xC0,0x33,0xC7,0xB0,0xB4,0x5C,0x7C,0x46,0x15,0x10,0x1B,0x76,0x9F,0x6B,0x62,0xD9,0x13,0x77,0x44,0x60,0x2F,0x4D,0x84,0x98,0xDD,0x7D,0x83,0x2D,0xAB,0xB0,0x57,0xAE,0x7B,0x8C,0x1C,0x8F,0x7B,0xD8,0x8F,0x74,0x58,0xE1,0xD9,0xAD,0xAF,0x1C,0xA8,0xFC,0xC5,0xC,0x84,0x9F,0x77,0x66,0x61,0x8A,0x74,0x74,0x70,0xF5,0xA9,0xB7,0x3B,0x16,0xFD,0xD0,0xF1,0x30,0x3F,0xA1,0xFE,0xCC,0x5C,0xAF,0xDF,0x46,0xD6,0xCA,0x35,0x8C,0x71,0xF1,0x18,0x23,0x30,0x70,0xAD,0x6B,0x7F,0x4B,0xFB,0x23,0xB2,0xDF,0xFA,0x2F,0xAE,0xC7] address = 0x401E79 i =0 while(i <= 118): a = Byte(address + i) ^ arr[i] PatchByte(address + i,a) i = i + 1
接着处理一下即可对自解密函数进行反编译。
我们写出脚本可以得到flag后序遍历为”)[email protected]=-EFCSRXZYV^ferlsihzyxvt}{TL“。
arr = [0x7c,0x81,0x61,0x99,0x67,0x9b,0x14,0xea,0x68,0x87,0x10,0xec,0x16,0xf9,0x7,0xf2,0xf,0xf3,0x3,0xf4,0x33,0xcf,0x27,0xc6,0x26,0xc3,0x3d,0xd0,0x2c,0xd2,0x23,0xde,0x28,0xd1,0x1,0xe6] for i in range(36): for j in range(0,7,2): arr[i] ^= 1 << (j + i % 2) print(‘‘.join(map(chr,arr)))
函数 sub_401F3C()即确认flag后18位的顺序,我们进行恢复可以得到后十八位为”=^[email protected]+)fAxyzXZ234}“
然后flag即为”LCTF{this-RevlrSE=^[email protected]+)fAxyzXZ234}“。
原文地址:https://www.cnblogs.com/Fingerprint/p/10036094.html