【SCTF2020】get_up WriteUp

一道SCTF的逆向题,做了很久很久才做起,唉…

IDA打开,用shift+f12查找出现的字符串,再通过x交叉引用定位到主函数

根据伪代码,大概是判断我们输入的一个长度小于等于6的字符串,跟进判断函数看一看

看到32位的a-f+0-9的字符串,盲猜哈希,又因为输入的长度小于等于6,肯定能爆破出来,于是丢到cmd5网站上,解出来“sycsyc”

成功绕过第一个判断以后,下面的代码大致意思是查找.reioc段并且改为可写,然后用刚刚输入的字符串进行异或,这里用IDCPython脚本处理一下

可以看到处理完后.reioc段变成了这个样子(先u将数据转为未定义,再p转为函数)

第一个call是printf让你输入flag,第二个call比较关键。先读取输入的字符,要求长度为30,然后找到.ebata段并对其进行动态patch

具体的patch方法是,取输入的前5个字符,进行异或

再写脚本处理一下。前5个字符到底是什么呢?盲猜是4个字母+1个大括号,因此有“flag{”、“sctf{”、“SCTF{”、“FLAG{”四种可能的开头方式(以我心目中的可能性降序排序),因此全部试一遍 比赛官网上面写了flag格式


老样子,将被动态patch的数据转为函数,即可在f5里看到sub_*开头的函数啦



这里只要合理的用y来修改一下变量类型,就能更好的看清楚算法流程啦~
我们用c++写一下爆破脚本:

#include <iostream>

using namespace std;

int sub_401A70(int *a1, char *Str) {
	int v5[30];
	int v6 = 0;
	int v10 = 0;
	int v11 = 0;
	int v12[30] = { 128,85,126,45,209,9,37,171,60,86,149,196,54,19,237,114,36,147,178,200,69,236,22,107,103,29,249,163,150,217 };
	for (int i = 0; i < strlen(Str); ++i)
		v5[i] = Str[i];
	for (int j = 0; j < strlen(Str); ++j) {
		v11 = (v11 + 1) % 256;
		v10 = (a1[v11] + v10) % 256;
		a1[v11] = a1[v10] & ~a1[v11] | a1[v11] & ~a1[v10];
		a1[v10] = a1[v10] & ~a1[v11] | a1[v11] & ~a1[v10];
		a1[v11] = a1[v10] & ~a1[v11] | a1[v11] & ~a1[v10];
		v6 = (a1[v10] + a1[v11]) % 256;
		v5[j] ^= a1[v6];
	}
	for (int k = 0; k < 30; ++k)
		if (v5[k] != v12[k]) {
			return k + 1;
		}
	return 0;
}

int sub_404000(char *Str) {
	int v3[300];
	int v5 = 0;
	int v9[300];
	char Dst[40];
	char v11[9] = "syclover";
	memset(Dst, 0, 0x28u);
	for (int i = 0; i < strlen(Str); ++i)
		Dst[i] = Str[i];
	for (int j = 0; j < 256; ++j) {
		v9[j] = j;
		v3[j] = v11[j % 8];
	}
	for (int k = 0; k < 256; ++k) {
		v5 = (v3[k] + v9[k] + v5) % 256;
		int tmp = v9[k];
		v9[k] = v9[v5];
		v9[v5] = tmp;
	}
	return sub_401A70(v9, Dst);
}

int main()
{
	char flag[] = "SCTF{111111111111111111111111}";
	for (int i = 5; i < 29; i++)
		flag[i] = 1;
	for (int i = 5; sub_404000(flag);)
		if (sub_404000(flag) == i + 1)
			flag[i]++;
		else
			i++;
	cout << flag;
}

成功爆破出flag!

SCTF{zzz~(|3[___]_rc4_5o_e4sy}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值