REVERSE-COMPETITION-HWS-5TH-2022
- re1
- re2
- re3
re1
64位exe,ida打开,来到main函数
输入的长度应为32,输入经过TEA加密,密文与已知的cipher进行比较
进入TEA函数,发现是魔改TEA,需一次性传入8个unsigned int,delta已知,key已知
用C还原出程序的魔改TEA加密过程,对解密过程进行相应的修正,解密得到flag
#include <stdio.h>
#include <stdint.h>//加密函数
void encrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k) {uint32_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3],v4 = v[4], v5 = v[5],v6 = v[6], v7 = v[7],sum = 0;int v15,v17=12;do{sum -= 0x61C88647;v0 += ((sum ^ v1) + (k[(sum >> 2) & 3] ^ v7)) ^ (((16 * v7) ^ (v1 >> 3)) + ((v7 >> 5) ^ (4 * v1)));v[0] = v0;v1 += ((k[(sum >> 2) & 3 ^ 1] ^ v0) + (sum ^ v2)) ^ (((16 * v0) ^ (v2 >> 3)) + ((v0 >> 5) ^ (4 * v2)));v[1] = v1;v2 += ((sum ^ v3) + (k[(sum >> 2) & 3 ^ 2] ^ v1)) ^ (((16 * v1) ^ (v3 >> 3)) + ((v1 >> 5) ^ (4 * v3)));v[2] = v2;v3 += ((sum ^ v4) + (k[(sum >> 2) & 3 ^ 3] ^ v2)) ^ (((16 * v2) ^ (v4 >> 3)) + ((v2 >> 5) ^ (4 * v4)));v[3] = v3;v4 += ((sum ^ v5) + (k[(sum >> 2) & 3] ^ v3)) ^ (((16 * v3) ^ (v5 >> 3)) + ((v3 >> 5) ^ (4 * v5)));v[4] = v4;v5 += ((k[(sum >> 2) & 3 ^ 1] ^ v4) + (sum ^ v6)) ^ (((16 * v4) ^ (v6 >> 3)) + ((v4 >> 5) ^ (4 * v6)));v[5] = v5;v6 += (((sum ^ v7) + (k[(sum >> 2) & 3 ^ 2] ^ v5)) ^ (((16 * v5) ^ (v7 >> 3)) + ((v5 >> 5) ^ (4 * v7))));v[6] = v6;v7 += (((sum ^ v0) + (k[(sum >> 2) & 3 ^ 3] ^ v6))) ^ (((16 * v6) ^ (v0 >> 3))+ ((v6 >> 5) ^ (4 * v0)));v[7] = v7;v15 = v17-- == 1;}while(!v15);printf("sum==0x%x\n",sum);
}//解密函数
void decrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k) {uint32_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3],v4 = v[4], v5 = v[5],v6 = v[6], v7 = v[7],sum = 0x6a99b4ac;int v15,v17=12;do{v7 -= (((sum ^ v0) + (k[(sum >> 2) & 3 ^ 3] ^ v6))) ^ (((16 * v6) ^ (v0 >> 3))+ ((v6 >> 5) ^ (4 * v0)));v[7] = v7;v6 -= (((sum ^ v7) + (k[(sum >> 2) & 3 ^ 2] ^ v5)) ^ (((16 * v5) ^ (v7 >> 3)) + ((v5 >> 5) ^ (4 * v7))));v[6] = v6;v5 -= ((k[(sum >> 2) & 3 ^ 1] ^ v4) + (sum ^ v6)) ^ (((16 * v4) ^ (v6 >> 3)) + ((v4 >> 5) ^ (4 * v6)));v[5] = v5;v4 -= ((sum ^ v5) + (k[(sum >> 2) & 3] ^ v3)) ^ (((16 * v3) ^ (v5 >> 3)) + ((v3 >> 5) ^ (4 * v5)));v[4] = v4;v3 -= ((sum ^ v4) + (k[(sum >> 2) & 3 ^ 3] ^ v2)) ^ (((16 * v2) ^ (v4 >> 3)) + ((v2 >> 5) ^ (4 * v4)));v[3] = v3;v2 -= ((sum ^ v3) + (k[(sum >> 2) & 3 ^ 2] ^ v1)) ^ (((16 * v1) ^ (v3 >> 3)) + ((v1 >> 5) ^ (4 * v3)));v[2] = v2;v1 -= ((k[(sum >> 2) & 3 ^ 1] ^ v0) + (sum ^ v2)) ^ (((16 * v0) ^ (v2 >> 3)) + ((v0 >> 5) ^ (4 * v2)));v[1] = v1;v0 -= ((sum ^ v1) + (k[(sum >> 2) & 3] ^ v7)) ^ (((16 * v7) ^ (v1 >> 3)) + ((v7 >> 5) ^ (4 * v1)));v[0] = v0;sum += 0x61C88647;v15 = v17-- == 1;}while(!v15);printf("sum==0x%x\n",sum);
}//打印数据 hex_or_chr: 1-hex 0-chr
void dump_data(uint32_t * v,int n,bool hex_or_chr)
{if(hex_or_chr){for(int i=0;i<n;i++){printf("0x%x,",v[i]);}}else{for (int i = 0; i < n; i++){for (int j = 0; j < sizeof(uint32_t)/sizeof(uint8_t); j++){printf("%c", (v[i] >> (j * 8)) & 0xFF);}}}printf("\n");return;
}int main()
{// v为要加解密的数据uint32_t v[] = { 0x10bd3b47,0x6155e0f9,0x6af7ebc5,0x8d23435f,0x1a091605,0xd43d40ef,0xb4b16a67,0x6b3578a9 };// k为加解密密钥uint32_t k[6] = { 0x1234, 0x2345, 0x4567, 0x6789, 0, 0 };// num_rounds,建议取值为32unsigned int r = 32;int n = sizeof(v) / sizeof(uint32_t);/*printf("加密前明文数据:");dump_data(v,n,1);for(int i=0;i<n/2;i++){encrypt(r,&v[i*2], k);}*/printf("加密后密文数据:");dump_data(v,n,1);/*for(int i=0;i<n/2;i++){decrypt(r,&v[i*2], k);}*/decrypt(0,v,k);printf("解密后明文数据:");dump_data(v,n,1);printf("解密后明文字符:");dump_data(v,n,0);return 0;
}// 7f943921724d63dc0ac9c6febf99fa88
re2
32位exe,ida打开,来到main函数
main函数读取输入,没有对输入的其他处理
对输入查找交叉引用,来到sub_4013D0函数,输入和下标异或,结果与已知的res比较
解异或得知是假flag,左边函数窗口看到tls,有一段SMC
解SMC,在StartAddress处创建函数,反编译,输入和byte_41B30A异或,调试得到byte_41B30A==0x48
然后对输入进行RC4加密,密钥为"Qfrost",密文为0x401307地址处开始的28个字节
解密RC4,再异或0x48即可得到flag
#include<stdio.h>/*
RC4初始化函数
*/
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{unsigned int i = 0, j = 0;char k[256] = { 0 };unsigned char tmp = 0;for (i = 0; i < 256; i++) {s[i] = i;k[i] = key[i % Len_k];}for (i = 0; i < 256; i++) {j = (j + s[i] + k[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;}
}/*
RC4加解密函数
unsigned char* Data 加解密的数据
unsigned long Len_D 加解密数据的长度
unsigned char* key 密钥
unsigned long Len_k 密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{unsigned char s[256];rc4_init(s, key, Len_k);int i = 0, j = 0, t = 0;unsigned long k = 0;unsigned char tmp;for (k = 0; k < Len_D; k++) {i = (i + 1) % 256;j = (j + s[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;t = (s[i] + s[j]) % 256;Data[k] = Data[k] ^ s[t] ^ 0x48;}
}
int main()
{//字符串密钥unsigned char key[] = "Qfrost";unsigned long key_len = sizeof(key) - 1;/*//数组密钥unsigned char key[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};unsigned long key_len = sizeof(key);*///加解密数据unsigned char data[] = {0x7F, 0xB6, 0x88, 0x12, 0xDC, 0xC3, 0xDE, 0xDB, 0x30, 0x24, 0xE3, 0xC1, 0x0F, 0xC9, 0x7F, 0xC2, 0x4D, 0x9C, 0x6B, 0x02, 0x26, 0x20, 0xF1, 0x25, 0xA0, 0xE3, 0xC6, 0xDE };//加解密rc4_crypt(data, sizeof(data), key, key_len);for (int i = 0; i < sizeof(data); i++){printf("%c", data[i]);}printf("\n");return 0;
}// QDbg-Is_an_1ntereSting-Game!
re3
安卓逆向,jadx-gui打开
输入的长度应小于420,trans是将输入的字符,三个一组,转成36进制,每组存储为两个字节
ida打开so文件,Java_com_example_ctf_MainActivity_check没什么用
对输入的校验在JNI_OnLoad的sub_D060方法
通过调试知道,for循环将传入的36进制转为16进制,这里会被char类型截断
然后是RSA加密,n和e已知,密文和sure_flag的20个字节比较
解RSA,将明文用16进制表示,每两个16进制转成三个10进制,不足三位的补0即可
import gmpy2
n=0x7019325b70f4a2f26e921102a0206de415caeb535cd4ec9d23d6608630dd00a9db5db8faef4621ccb2e775844c7447a1a843ebac03eca6f329feabcd6560b80aacf7a54a298548827c9d75e1450fcf7e53dac37c0f7fd25d509c342c23bda0619504b28ec903c56c87
p=1475203612633975218848450285487339190962027688336790188873776418606441616307026173067
q=1475203612633975218848450285487339190962027688336790188873776418606441616307046219549
r=1475203612633975218848450285487339190962027688336790188873776418606441616307129708089
e=0x10001
phin=(p-1)*(q-1)*(r-1)
d=gmpy2.invert(e,phin)
c=0x4920616D207375726520697420697320666C3467
m=gmpy2.powmod(c,d,n)
s=hex(m)[2:]
flag=""
for i in range(0,len(s),2):tmp=int(s[i:i+2],16)if tmp<100:flag+="0"flag+=str(tmp)
print(flag)
# 037087131219012107229231067248093076089082070175138132195124126254031088197066063081248248223201185154047168242228140155089071245228045160218140167117182217137118206104215018068031237111113041220252131252040018130017184197145113066057103096226240251147039224115177108218078236161028053035089246229073211242029209057
输入验证成功,但是貌似多解,不太理解怎么回事