当时打完比赛跟着复现过一遍,好多都是跟着WP做的,变形的RC4也没理清楚,现在重新独立做一遍。
题目附件:https://n0zom1z0.lanzoup.com/iqoFf1mq6n8h
CPP,没有完全去符号,用了一堆C++的特性,还有诸如类、成员函数这些disgusting的逆向元素。。
整体流程:
cipher的赋值点:
先看XTEA:
text_79
:
这里的v11对应的XTEA的DELTA:
这里可以得到XTEA的循环轮数为0x100:
然后就是disgusting大合集了:
对比下运算和>>11
,&3
,可以比较容易的知道是XTEA算法:
注意下顺序,先是两个v0,v1的,最后再加DELTA。
然后看RC4:
前面部分都没有魔改:
在swap完后,跟正常的RC4相比,多了一次xor的操作:
这里可以结合动态调试来分析下一些关键的点,然后能写出改动后的核心部分:
即 xor1,add,xor2
那么对应的逆向解回去:
当然,也可以像我当时复现时看WP的,直接dump出这三个数组(xor1,add,xor2),难度都不大。
这样,先解RC4,转DWORD后,解XTEA,换个端序即可得到flag.
rc4:
c
#include<bits/stdc++.h>
using namespace std;
signed main(){
int base64_table[] = {0x33, 0xB2, 0x49, 0x8C, 0x39, 0xDD, 0x60, 0x5F, 0x5F, 0x77,
0x72, 0xAB, 0x38, 0xD9, 0xED, 0xE7, 0xF3, 0xF0, 0x66, 0x67,
0x16, 0xC8, 0x53, 0x80, 0x71, 0xB2, 0xFA, 0x5E, 0x7C, 0x2B,
0xBB, 0x0B, 0xE5, 0x88, 0x82, 0x0B, 0x06, 0x8C, 0x8D, 0xAD,
0x47, 0xB5, 0x85, 0xBB, 0x06, 0x8D, 0x01, 0x2B };
string key = "gaLf_Ek@f_A_s1_sih7";
int s[256],k[256];
int j=0;
for (int i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % key.length()];
}
for (int i2 = 0; i2 < 256; i2++) {
j = (s[i2] + j + k[i2]) & 255;
int temp = s[i2];
s[i2] = s[j];
s[j] = temp;
}
int j2 = 0;
int i3 = 0;
for (int i4 : base64_table) {
// i3 = (i3 + 1) & 255; // 1
// j2 = (s[i3] + j2) & 255; // s[1] + 0 = 0xEE
// int temp2 = s[i3];
// s[i3] = s[j2];
// s[j2] = temp2; // swap(s[1],s[0xEE])
// int rnd = s[(s[i3] + s[j2]) & 255];
// int v21 = (i4 ^ rnd);
// int v23 = s[i3];
// int v24 = s[j2];
// int v20 = v21 + v23;
// int v25 = v24 ^ v20;
// cout << v25 % 0x100;
i3 = (i3 + 1) & 255; // 1
j2 = (s[i3] + j2) & 255; // s[1] + 0 = 0xEE
int temp2 = s[i3];
s[i3] = s[j2];
s[j2] = temp2; // swap(s[1],s[0xEE])
int rnd = s[(s[i3] + s[j2]) & 255];
int v23 = s[i3];
int v24 = s[j2];
int v20 = i4 ^ v24;
int v21 = (v20 - v23) & 0xFF;
cout <<( v21 ^ rnd )<<",";
}
}
tea.cpp
c
#include <stdio.h>
#include <stdint.h>
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0xDEADBEEF;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 2) ^ (v1 >> 7)) + v1) ^ (sum + key[sum & 3]);
v1 += (((v0 << 6) ^ (v0 >> 3)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum += delta;
}
v[0]=v0; v[1]=v1;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0xDEADBEEF, sum=+delta*num_rounds;
for (i=0; i < num_rounds; i++) {
sum -= delta;
v1 -= (((v0 << 6) ^ (v0 >> 3)) + v0) ^ (sum + key[(sum>>11) & 3]);
v0 -= (((v1 << 2) ^ (v1 >> 7)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t v[12]={3320791996, 1852925827, 2794088750, 3032168981, 2247472955, 2257807924, 1534038864, 3924795740, 2794088750, 3032168981, 2247472955, 2257807924};
uint32_t const k[4]={0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476};
unsigned int r=0x100;
decipher(r, v, k);
decipher(r,(uint32_t*)(v+2),k);
decipher(r,(uint32_t*)(v+4),k);
decipher(r,(uint32_t*)(v+6),k);
decipher(r,(uint32_t*)(v+8),k);
decipher(r,(uint32_t*)(v+10),k);
for(int i=0;i<12;i++)
printf("%d,",v[i]);
return 0;
}
py
cipher = [
0x33, 0xB2, 0x49, 0x8C, 0x39, 0xDD, 0x60, 0x5F, 0x5F, 0x77,
0x72, 0xAB, 0x38, 0xD9, 0xED, 0xE7, 0xF3, 0xF0, 0x66, 0x67,
0x16, 0xC8, 0x53, 0x80, 0x71, 0xB2, 0xFA, 0x5E, 0x7C, 0x2B,
0xBB, 0x0B, 0xE5, 0x88, 0x82, 0x0B, 0x06, 0x8C, 0x8D, 0xAD,
0x47, 0xB5, 0x85, 0xBB, 0x06, 0x8D, 0x01, 0x2B
]
aaa_cipher = [
0x8A, 0x18, 0x65, 0x89, 0xCA, 0xB6, 0x63, 0xF2, 0x8A, 0x18, 0x65, 0x89, 0xCA, 0xB6, 0x63, 0xF2, 0x8A, 0x18, 0x65, 0x89, 0xCA, 0xB6, 0x63, 0xF2, 0x8A, 0x18, 0x65, 0x89, 0xCA, 0xB6, 0x63, 0xF2, 0x8A, 0x18, 0x65, 0x89, 0xCA, 0xB6, 0x63, 0xF2, 0x8A, 0x18, 0x65, 0x89, 0xCA, 0xB6, 0x63, 0xF2
]
rc4_table = [
0x31, 0xEE, 0x17, 0x80, 0xE3, 0x2D, 0x0A, 0xE5, 0x53, 0x33, 0x9E, 0x2E, 0x1D, 0x05, 0x6F, 0xB4,
0x51, 0x9A, 0x36, 0x5C, 0xBD, 0x08, 0xA2, 0x34, 0xA3, 0x65, 0x59, 0x62, 0xAE, 0xEF, 0x0D, 0xD0,
0xBC, 0x30, 0x81, 0xEB, 0x8C, 0xE8, 0x22, 0xFD, 0x7E, 0x4A, 0x1E, 0x10, 0x27, 0xDD, 0x5A, 0xA4,
0x0B, 0x29, 0xD5, 0x61, 0x9C, 0x48, 0x6E, 0x7D, 0xF1, 0xBE, 0x90, 0xB3, 0x55, 0x1B, 0x74, 0x89,
0x60, 0x6C, 0xC1, 0x76, 0x3B, 0x8F, 0xD4, 0x6B, 0x44, 0xE7, 0x49, 0x1F, 0xFB, 0x7C, 0x5B, 0x0F,
0x86, 0xA8, 0xB0, 0xA7, 0xCF, 0x5E, 0xC9, 0xCC, 0x13, 0xB6, 0x03, 0x4D, 0xD1, 0xE4, 0x6D, 0xBB,
0xF4, 0xA1, 0x37, 0xF9, 0x00, 0x38, 0xFE, 0x14, 0x42, 0x3C, 0x4C, 0x7A, 0x0C, 0x6A, 0x26, 0x01,
0xA6, 0x70, 0x02, 0x87, 0xE2, 0x04, 0x45, 0x50, 0x3E, 0x58, 0xA9, 0x52, 0x23, 0x82, 0x20, 0x7F,
0x39, 0x75, 0xC6, 0xB7, 0x9B, 0xF8, 0x21, 0xA0, 0x8E, 0xC2, 0xBA, 0xD2, 0x35, 0x5F, 0xBF, 0x06,
0x16, 0xC3, 0x32, 0xAB, 0xB2, 0x68, 0x2C, 0xF7, 0xAD, 0x96, 0x09, 0x8A, 0x2A, 0xF5, 0x8B, 0x7B,
0x19, 0x8D, 0x4E, 0x93, 0xFF, 0x78, 0xEC, 0xD7, 0x25, 0x9D, 0xD3, 0x64, 0xCA, 0xAA, 0xCB, 0xD8,
0xE0, 0x24, 0x46, 0xB5, 0xD6, 0xD9, 0xC7, 0x0E, 0x98, 0xAF, 0x85, 0xFC, 0x41, 0x94, 0x91, 0xC8,
0xC4, 0x63, 0x84, 0xF6, 0xC0, 0x07, 0x69, 0x88, 0x1C, 0x11, 0x18, 0x3A, 0x72, 0x47, 0x4B, 0xF0,
0xDE, 0x73, 0x66, 0xDA, 0xEA, 0x54, 0xF2, 0xA5, 0x3D, 0x79, 0x71, 0x1A, 0x15, 0x3F, 0x40, 0x92,
0xCD, 0xC5, 0xB9, 0x57, 0xDF, 0xAC, 0xFA, 0x99, 0x95, 0x5D, 0xE1, 0x77, 0x9F, 0xDC, 0x56, 0xB8,
0x43, 0xE9, 0x12, 0x2F, 0x83, 0x2B, 0x28, 0x4F, 0xE6, 0xF3, 0xDB, 0xCE, 0xB1, 0x97, 0xED, 0x67
]
add = [0x56,0x2d,0xf8,0x42,0x7f,0xc2,0x26,0x63,0x83,0x32,0xc4,0x3f,0xb9,0xa8,0x7f,0xc9,0x43,0x22,0xc6,0x89,0x6b,0x5d,0xef,0x2e,0xe8,0x20,0xcd,0xbf,0x84,0xf0,0x7b,0x4d,0xd2,0x3f,0x4f,0xb7,0x95,0xf0,0xcd,0x96,0x57,0x56,0x43,0xf1,0x6b,0x1,0xc6,0x36]
xor1 = [0x3b,0x3b,0x3e,0xe8,0x2c,0x72,0x2e,0xc7,0xc7,0xde,0x12,0xd1,0x91,0x34,0x61,0x59,0x1d,0x13,0x81,0xd4,0x87,0x67,0xeb,0x73,0x7c,0x58,0xa4,0x6a,0x98,0x97,0x1f,0x83,0x2d,0xa3,0x90,0x76,0xdb,0xf0,0x18,0x89,0x8d,0xe2,0xa7,0x2e,0x44,0xbc,0x4c,0x6c]
xor2 = [0xee,0x17,0x80,0xe3,0x17,0xa,0xe5,0x53,0x33,0x9e,0x2e,0x1d,0x5,0x6f,0xb4,0x51,0x9a,0x36,0x5c,0xbd,0x8,0xa2,0x34,0xa3,0x65,0x59,0x62,0xae,0x34,0xd,0xd0,0xbc,0x30,0x81,0xeb,0x8c,0x65,0x36,0xfd,0x7e,0x4a,0x1e,0x10,0x27,0xdd,0x5a,0xa4,0xb]
def enc_rc4():
"""
xor1
add
xor2
"""
pass
def dec_rc4(ct):
pt= []
for i in range(len(ct)):
x = ((ct[i]^xor2[i])-add[i])^xor1[i]
x &= 0xff
pt.append(x)
return pt
pt = dec_rc4(cipher)
assert(len(pt)==48)
pt = [188,67,239,197,131,103,113,110,46,105,138,166,21,58,187,180,59,183,245,133,52,106,147,134,80,147,111,91,92,161,239,233,46,105,138,166,21,58,187,180,59,183,245,133,52,106,147,134]
DWORD_pt = []
for i in range(12):
x = pt[i*4:i*4+4]
DWORD_pt.append((x[3]<<24)+(x[2]<<16)+(x[1]<<8)+x[0])
print(DWORD_pt)
# [3320791996, 1852925827, 2794088750, 3032168981, 2247472955, 2257807924, 1534038864, 3924795740, 2794088750, 3032168981, 2247472955, 2257807924]
flag = [1681417828,945971512,842162999,909718369,1714500656,1701077561,808739126,943273059,842162999,909718369,1714500656,1701077561]
from libnum import *
for c in flag:
print(n2s(c)[::-1].decode(),end='')
DASCTF{df8d8ab87c22a396041f9bde6a40c4987c22a396041f9bde}
总结:静下心来,花1h+逆向就好了。