[RCTF 2022] Reverse赛题复现

突然发现还没搞完,占个坑先,也不知道什么时候填上(心虚)

huowang

大概是qemu起了一个新的迷宫,然后又走了check里面那个map的迷宫,两个迷宫都得走过才算对。

学长用unicorn模拟把这玩意解出来的,但我现在还不会unicorn,只能来试试啥卵爆破解法。(寒假一定学会unicorn(确信))

直接dfs,能爆出来就行

import subprocess
import sys

map = [
    "* *********************",
	"* *     *       *     *",
	"* * * * *** * *** * * *",
	"*   * *     * *   * * *",
	"* * * ********* * *** *",
	"* * *     *     * *   *",
	"* * ***** * * ***** * *",
	"*   * *   *         * *",
	"*** * * *** * *** *** *",
	"*   * *   * * *   *   *",
	"* *** *** * * *   *** *",
	"*   * *   * * *     * *",
	"* * * * *** * ***** * *",
	"* *   *         *   * *",
	"* *********** *** * * *",
	"*   *     *       * * *",
	"* ********* ********* *",
	"*   ** ***  *       * *",
	"*   * **** ** ***** * *",
	"*   * *  *    *     * *",
	"* * * * * ***** ***** *",
	"*       *     *       *",
	"*********************E*"
]
vis = [[False for j in range(25)] for i in range(25)]
def dfs(x, y, path):
	if x < 0 or x >= 23:
		return
	if y < 0 or y >= 23:
		return
	if vis[x][y] == True:
		return
	if map[x][y] == '*':
		return
	if map[x][y] == 'E':
		file = './HuoWang'
		p = subprocess.Popen([file], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

		p.stdin.write(path.encode())
		p.stdin.close()

		result = p.stdout.read()
		p.stdout.close()
		print(result)
		if b'GrandFather' in result:
			print(path)
	vis[x][y] = True
	dfs(x - 1, y, path + 'w')
	dfs(x + 1, y, path + 's')
	dfs(x, y - 1, path + 'a')
	dfs(x, y + 1, path + 'd')
	vis[x][y] = False

dfs(0, 1, '')
print("OOOps")

结果跑出来两个解:

第一个的路径是:sssssssddwwwwwwddssssddddssaassddssaassddddwwwwwwwwddddwwddwwddddssssaassaassaassddddssaassaaaaaassassdddwwddddddssaaaassdddddds
RCTF{79081c1b246fc9a59f684cb4e454b8a3}

第二个的路径是:sssddwwddssssddddssaassddssaassddddwwwwwwwwddddwwddwwddddssssaassaassaassddddssaassaaaaaassassdddwwddddddssaaaassdddddds
RCTF{e1f9e3d166dcec5ecff3a2c5fbdeab3b}

赛中给了hint是最短路,那就是第二个了

RTTT

这rust又臭又长还不给符号表,呃呃了

函数的主要逻辑在sub_EBF0中。上动调,发现两组大小为20的数据在之后的一个while循环里异或

提出来手动异或一下

v229 = [125, -12, -124, -33, 78, 49, 27, -5, 45, -26, 88, -33, 84, -108, -121, -41, -46, -43, -5, -48]
v227 = [42, -111, -24, -68, 126, 92, 126, -37, 89, -119, 120, -115, 23, -64, -63, -9, -32, -102, -55, -30]

for i in range(20):
    print(chr(v229[i] ^ v227[i]), end="")

发现是Welc0me to RCTF 2O22

接着往下调,在sub_E310里面发现了0x100和取模,以及最后一步是异或操作,可以联想到可能是RC4,那么之前的Welc0me to RCTF 2O22大概率是key,直接解密一下E310后面的42个字符发现解出来是:

C7DD9165-R-72--}332DE0CBEF9C{1776T7DF3DCEF,一眼顺序有问题。

考虑输入42位字符0123456789abcdefghijklmnopqrstuvwxyzABCDEF然后去动调映射一下,最好找的地方就是RC4最后一步异或那,肯定会有当前的密文

从0123456789abcdefghijklmnopqrstuvwxyzABCDEF变到了ozpBaxmtn0sqjdiF8fcyr57b93w14EgAD2uCk6lveh,RC4是个对称加密,那么我们开始对得到的结果也映射一下

#include <bits/stdc++.h>
using namespace std;
void init(int *s, char *key, int len)
{
	int t[256] = {0};
	char tmp = 0;
	for (int i = 0; i < 256; ++i)
	{
		s[i] = i;
		t[i] = key[i % len];
	}
	int j = 0;
	for (int i = 0; i < 256; ++i)
	{
		j = (j + s[i] + t[i]) % 256;
		swap(s[i], s[j]);
	}
}
void crypt(int *s, char *data, int len)
{
	int i = 0, j = 0, t = 0;
	char tmp;
	for (int k = 0; k < len; ++k)
	{
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		swap(s[i], s[j]); 
		t = (s[i] + s[j]) % 256;
		data[k] ^= s[t];
	}
}
char orig[233] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEF";
char end[233] = "ozpBaxmtn0sqjdiF8fcyr57b93w14EgAD2uCk6lveh";
int pos[233];
char data[233] = {0x34, 0xc2, 0x65, 0x2d, 0xda, 0xc6, 0xb1, 0xad, 0x47, 0xba, 0x6, 0xa9, 0x3b, 0xc1, 0xcc, 0xd7, 0xf1, 0x29, 0x24, 0x39, 0x2a, 0xc0, 0x15, 0x2, 0x7e, 0x10, 0x66, 0x7b, 0x5e, 0xea, 0x5e, 0xd0, 0x59, 0x46, 0xe1, 0xd6, 0x6e, 0x5e, 0xb2, 0x46, 0x6b, 0x31};
char key[233] = "Welc0me to RCTF 2O22";
int s[260];
int main()
{
	int len = strlen(key);
	init(s, key, len);
	len = strlen(data);
	crypt(s, data, len);
	for (int i = 0; i < 42; ++i)
	{
		for (int j = 0; j < 42; ++j)
		{
			if (orig[i] == end[j])
			{
				pos[i] = j;
				break;
			}
		}
	}
	for (int i = 0; i < 42; ++i) cout << data[pos[i]];
	return 0;
}

得到flag:RCTF{03C3E9B2-E37F-2FD6-CD7E-57C91D77DD61}

rdefender

依然是rust,感谢出题人没去符号表。这个题赛中好像是个交互题,我线下复现只能大概分析一波了

main函数里会发现一个字符串叫flag,动调会报错"No such file or directory",分析一下逻辑应该是读取了叫flag的文件,动调会发现src_8保存了flag文件内的数据在内存中的地址信息

checkserver

带了个html,检查程序的时候没看出啥玩意来,字符串窗口有"[SUCCESS] Auth Success"和"[ERROR] Auth Fail"这种字符串,然后还有下面那一大串,第一反应是:这是个http服务器吗??这tm是逆向吗???

来到字符串authcookie的位置,\r\n\r\n是两个换行,联想一下,POST请求的body和header之间也是俩换行,这应该是个POST请求吧大概,大胆猜下面发了个authcookie的包(这真不是web题?)

loc_404530里面带花指令,研究了一下发现那些一大坨的数据块都是脏字节,没有任何作用,上面的jnz应该是恒为真的,把数据块全给nop掉就可以反汇编了。这里面的花指令也是一样的

402040里面看起来是个奇奇怪怪的加密,观感上是上面两个xmm里面的数据经过这个奇奇怪怪的加密后会变成下面那俩xmm,然后Auth Fail和Auth Success就是提示check是否成功的。那现在准备发包动调吧

strace ./checkserver可以检查到端口为8080

配个burpsuite先

posted @ 2023-01-31 17:43  iPlayForSG  阅读(216)  评论(0编辑  收藏  举报