【GACTF】EasyRe WriteUp

本文详细介绍了在GACTF比赛中遇到的一个动态patch的逆向工程问题。通过使用IDA和GDB,作者揭示了一个虚拟机的初始化过程和复杂的opcode分析。通过对opcode的深入理解和脚本辅助,成功解密了flag的生成逻辑,最终得出flag为GACTF{c7ack_m3_sh3ll_smc_vm_0k?}。
摘要由CSDN通过智能技术生成

IDA打开直接能看到main函数



可以看到,在执行sub_8048838前,调用了前一个函数,对它进行动态patch(直接点进去sub_8048838会发现是无意义代码)
这个动态patch代码的算法有点复杂,直接gdb下断点然后dump memory ./dmp 0x8048838 0x8048de0,然后用WinHex把dump出来的替换掉原本的,IDA重新打开patch后的,就可以了

可以看出来,这是一个虚拟机,main函数里有对其进行初始化的函数

同样在main函数中我们可以找到opcode的位置

用IDAPython导出一下,得到

分析opcode真的难受。。。我简单分析了一下(你看不懂没关系,我自己写的通常只有我看得懂QAQ)

我们可以看到,以opcode-161作为分界线,前面的是对我们一开始输入的%lld进行各种变换和各种比较,不对就退出,对的话,又会对dA0、dA4、dA8、dAC赋值
后面开始,就是逐位对我们输入的flag进行异或,然后和一个数比较,异或的数是前面提到的被赋值的4个地址的数之一
根据flag的格式是GACTF{xxx},而前4次比较直接把4个数都用过一遍了,于是可以直接逆推这4个数,所以opcode-161之前的可以完全不用管了
写个脚本,提取opcode里面的数据,生成了下面的代码

int main()
{
	cout << char(11 + 256 ^ 332);
	cout << char(122 ^ 59);
	cout << char(149 ^ 214);
	cout << char(6 + 256 ^ 338);
	cout << char(125 ^ 59);
	cout << char(173 ^ 214);
	cout << char(47 + 256 ^ 332);
	cout << char(101 + 256 ^ 338);
	cout << char(45 + 256 ^ 332);
	cout << char(47 + 256 ^ 332);
	cout << char(57 + 256 ^ 338);
	cout << char(13 + 256 ^ 338);
	cout << char(187 ^ 214);
	cout << char(8 ^ 59);
	cout << char(13 + 256 ^ 338);
	cout << char(63 + 256 ^ 332);
	cout << char(58 + 256 ^ 338);
	cout << char(97 + 256 ^ 338);
	cout << char(87 ^ 59);
	cout << char(32 + 256 ^ 332);
	cout << char(13 + 256 ^ 338);
	cout << char(63 + 256 ^ 332);
	cout << char(63 + 256 ^ 338);
	cout << char(181 ^ 214);
	cout << char(19 + 256 ^ 332);
	cout << char(160 ^ 214);
	cout << char(33 + 256 ^ 332);
	cout << char(13 + 256 ^ 338);
	cout << char(11 ^ 59);
	cout << char(57 + 256 ^ 338);
	cout << char(115 + 256 ^ 332);
	cout << char(70 ^ 59);
}

跑出来即可

GACTF{c7ack_m3_sh3ll_smc_vm_0k?}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值