admin管理员组

文章数量:1530015

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,建议取值为32
	unsigned 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

输入验证成功,但是貌似多解,不太理解怎么回事

本文标签: competitionREVERSEHWS