[GWCTF 2019]xxor

[GWCTF 2019]xxor

首先可以到汇编界面从新定义(U+P)一下main函数,不然看着会有点乱

分析

image-20241031153217983

追踪input变量

可以看到每次循环是获取四字节的输入

但后面对于tmp变量的赋值我就有点看不懂了,不要紧,直接动调

动态调试

连接linux,下断点开调

image-20241031153509740

我不知道为什么输入字符会直接跳出循环,所以输入了数字

F8步过

image-20241031153551690

可以看到tmp1tmp2被赋值了第一次输入和第二次输入

分析tea_encode

image-20241031154643957

我们可以继续动调下去,可以看到v0和v1分别被赋值了tmp1tmp2的值,会这样的原因是(unsigned int *)&tmp1,这里tea_encode函数调用的是tmp1的地址,而tmp1tmp2的地址仅相差4字节,在使用a1[1]时,其实是a1的地址加上一个unsigned int指针的大小,即四字节,刚好就是tmp2的地址,这下就明白是如何赋值的了

继续跟进看如何赋值

此时tmp1tmp2加密后的值是这样image-20241031155321233

再看看v4是如何赋值的

image-20241031155350888

是将tmp2作为高地址,tmp1作为低地址拼接起来

按F4完成循环,v4进行了三次这样的赋值

image-20241031155540980

最后在sub_400770函数中进行比较

image-20241031155753051

这里a1是个_DWORD指针,类似与unsigned int指针,所以每次调用v4中四个字节的值

编写脚本

现在算是分析完了,把sub_400770函数中的值进行以每两组代入tea_encode就可以解出flag了

z3求解

from z3 import *

x2, x3, x4 = Ints('x2 x3 x4')
s = Solver()
s.add(x2 - x3 == 0x84A236FF)
s.add(x3 + x4 == 0xFA6CB703)
s.add(x2 - x4 == 0x42D731A8)

if s.check() == sat:
    result = s.model()
    # 转换为 Python 整数
    x2 = hex(result[x2].as_long())
    x3 = hex(result[x3].as_long())
    x4 = hex(result[x4].as_long())
print(x2, x3, x4)

魔改tea加密求解

tea对称加密,魔改轮数和加密算法,进行三轮加密

#include <iostream>
using namespace std;
int main() {
	unsigned int v[6] = { 0xDF48EF7E, 0x20CAACF4, 0xe0f30fd5, 0x5c50d8d6, 0x9e1bde2d, 0x84F30420 };
	int key[4] = { 2, 2, 3, 4 };
	int r = 64;
	for (int i = 0; i < 6; i += 2) {
		unsigned int v0 = v[i];
		unsigned int v1 = v[i + 1];
		unsigned int sum = 0x458BCD42 * r;
		for (int j = 0; j < r; j++) {
			v1 -= (v0 + sum + 20) ^ ((v0 << 6) + key[2]) ^ ((v0 >> 9) + key[3]) ^ 0x10;
			v0 -= (v1 + sum + 11) ^ ((v1 << 6) + *key) ^ ((v1 >> 9) + key[1]) ^ 0x20;
			sum -= 0x458BCD42;	
		}
		v[i] = v0;
		v[i + 1] = v1;
	}for (unsigned int i = 0; i < 6; i++) { 
		for (unsigned int j = 2; j < 3; j--) {    //转为大端序
			printf("%c", *((char*)&v[i] + j));   
		}
	}
}

解出flag flag{re_is_great!}

posted @ 2024-10-31 16:31  结城希亚  阅读(9)  评论(0编辑  收藏  举报