好好学逆向

moectf题真的好,每日一题

2025.6.19 考完试一定写🥲

2025.7.19 会写的会写的😫

A_game

1

好清晰的逻辑,好清晰的函数名🥲 首先输入49个字符的字符串,将这49个字符填入9x9的box数组中值为0的位置,经过3个check函数验证是否正确,如果正确,那么将str与magic数组异或得到flag

接下来我们查看check1函数的代码

2

每一行必须包含数字 1~9,不能重复,也不能缺少

check2函数:每一列必须包含数字 1~9,不能重复,也不能缺少

check3函数:每一个 3x3 小宫格中都包含 1~9 各一次

很明显,这是数独游戏的规则,我们需要填入正确的49个数字

直接用python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from typing import List

box=[0, 0, 5, 0, 0, 4, 3, 6, 0,
0, 0, 0, 0, 5, 0, 0, 2, 4,
0, 4, 9, 6, 7, 0, 0, 0, 0,
1, 0, 6, 0, 2, 0, 0, 3, 0,
9, 0, 0, 7, 0, 0, 1, 0, 8,
0, 3, 0, 0, 0, 5, 0, 9, 0,
2, 0, 0, 5, 0, 7, 0, 0, 9,
7, 0, 4, 0, 0, 0, 8, 0, 0,
0, 9, 0, 0, 4, 0, 0, 0, 6]

# 把box转换为二维列表
def to_grid(flat: List[int]) -> List[List[int]]:
return [flat[i*9:(i+1)*9] for i in range(9)]

# 数独求解器
def is_valid(grid, row, col, num):
for i in range(9):
if grid[row][i] == num or grid[i][col] == num:
return False
start_row, start_col = 3*(row//3), 3*(col//3)
for i in range(3):
for j in range(3):
if grid[start_row+i][start_col+j] == num:
return False
return True

def solve(grid):
for row in range(9):
for col in range(9):
if grid[row][col] == 0:
for num in range(1, 10):
if is_valid(grid, row, col, num):
grid[row][col] = num
if solve(grid):
return True
grid[row][col] = 0
return False
return True

# 记录原始空位
empty_indices = [i for i in range(81) if box[i] == 0]

# 解题并构造 Str
grid = to_grid(box.copy())
if solve(grid):
print("[+] Sudoku Solved:")
for row in grid:
print(row)

# 拼接填入空位的字符,作为 Str
Str = ''.join(str(grid[i//9][i%9]) for i in empty_indices)
print(f"\n[+] Final Str (49 input chars):\n{Str}")
else:
print("[-] No solution found.")

magic=[107, 2, 102, 112, 68, 105, 126, 110, 67, 74,
120, 74, 109, 96, 86, 0, 81, 89, 80, 67,
80, 81, 109, 116, 2, 85, 80, 82, 110, 111,
121, 64, 93, 75, 30, 25, 28, 116, 3, 84,
7, 76, 82, 106, 96, 80, 88, 64, 88]
flag = ''.join(chr(ord(Str[i]) ^ magic[i]) for i in range(49))
print(f"\n[+] Flag: moectf{{{flag}}}")

Android_Cracker

用jadx打开找到MainActivity打开就是了

Broken_hash

没做出来,复现一下

有一个师傅的解法很简单:

这个程序需要输入88位字符,经过变种SHA1算法转化,再和一个数组比较

先输入88个a,下断点动调

看到了加密后的数组,发现a变成0x0D7C1A410

3

所以可以输入abcdefghijklmnopqrstuvwxyz1234567890_!ABCDEFGHIJKLMNOPQRSTUVWXYZ{}aaaaaaaaaaaaaaaaaaaaaa

建立一个映射表

1
2
3
4
5
6
7
8
a = [0x64744C9A, 0x047C2FF1, 0xA2D74292, 0x85BEF77E, 0x711FCBF7, 0x669E1609, 0x6BBD9DB6, 0x6941C8A4, 0xB16E48B3, 0xDE321186, 0x5251E8C2, 0xFB8F95A7, 0x711FCBF7, 0xCB5C3FAD, 0x36568AF5, 0xFB8F95A7, 0x82ACF96A, 0x75DCD570, 0x7EF00E40, 0xFB8F95A7, 0x4BE9314A, 0xCB5C3FAD, 0xA2D74292, 0xDE321186, 0xFB8F95A7, 0x46927FA8, 0xB16E48B3, 0xD7C1A410, 0x567375C3, 0x711FCBF7, 0xFB8F95A7, 0x9C19F0F3, 0xD035E914, 0xFB8F95A7, 0x6941C8A4, 0x0B7D1395, 0xD7C1A410, 0xC87A7C7E, 0xFB8F95A7, 0xD7C1A410, 0xDE321186, 0x5251E8C2, 0xFB8F95A7, 0xD5380C52, 0xBEA99D3B, 0xCEDB7952, 0xFB8F95A7, 0x73456320,
0xD7C1A410, 0xDE321186, 0xFB8F95A7, 0x581D99E5, 0xA2D74292, 0x711FCBF7, 0xFB8F95A7, 0x06372812, 0xFB8F95A7, 0x73456320, 0xCEDB7952, 0xEF53E254, 0xFB8F95A7, 0x9F12424D, 0x669E1609, 0xFB8F95A7, 0x9C19F0F3, 0xFECF7685, 0x0B7D1395, 0x1833E8B1, 0xFB8F95A7, 0x9F66DD04, 0xA2D74292, 0xD7C1A410, 0xFB8F95A7, 0x6941C8A4, 0x866CAF4F, 0x047C2FF1, 0x64744C9A, 0xFB8F95A7, 0xD5380C52, 0xCEDB7952, 0xDE321186, 0x81453D43, 0xCB5C3FAD, 0xB16E48B3, 0xC578F843, 0xCEDB7952, 0xDE321186, 0xE38C6F07, 0x8B9E97A8, 0x8FDF9EDF, 0xD1868B96, 0x93AFD1D1, 0x8D8BDF85, 0x989EDF86, 0xDF91969E, 0xF5C3A0C1, 0x00000000][:88]
b = "abcdefghijklmnopqrstuvwxyz1234567890_!ABCDEFGHIJKLMNOPQRSTUVWXYZ{}aaaaaaaaaaaaaaaaaaaaaa"
c = [0x0D7C1A410, 0x9E3919E7, 0x85BEF77E, 0x5251E8C2, 0x0A2D74292, 0x669E1609, 0x5C1DFF11, 0x0CB5C3FAD, 0x0FECF7685, 0x0B0F33A9A, 0x1833E8B1, 0x0B7D1395, 0x64744C9A, 0x0DE321186, 0x47C2FF1, 0x0EF53E254, 0x1902B329, 0x866CAF4F, 0x4A528AE0, 0x711FCBF7, 0x0CEDB7952, 0x352B172C, 0x0AFEA7FF6, 0x3175EDAB, 0x0D035E914, 0x20D324AE, 0x0B16E48B3, 0x5C6054F, 0x36568AF5, 0x0BEA2375F, 0x567375C3, 0x0BF0FD0CB, 0x4BE9314A, 0x7F2A2EBE, 0x0C87A7C7E, 0x0BEA99D3B, 0x0FB8F95A7, 0x94D2FB03, 0x6372812, 0x46927FA8, 0x73456320, 0x4E3F843, 0x75DCD570, 0x6941C8A4,
0x581D99E5, 0x7EF00E40, 0x7A260E4D, 0x0C578F843, 0x17947C53, 0x786C70, 0x9C19F0F3, 0x1D795AC9, 0x9F12424D, 0x0AB021E08, 0x77ACB10, 0x0D1D0F68E, 0x82ACF96A, 0x9F66DD04, 0x8AD9BAF7, 0x0AAE6D8C9, 0x0E73CAEF, 0x0BFC92893, 0x0D5380C52, 0x81453D43, 0x6BBD9DB6, 0x0E38C6F07, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410, 0x0D7C1A410]
for i in a:
print(b[c.index(i)], end="")

官方wp:考察SEH,patch程序,以及编写交互脚本

本题使用了一个哈希算法(SHA1,魔改了部分参数)对flag每一位计算哈希,然后跟密文对比验证。当然,只取了最终哈希值的前4个字节(防止直接用SHA1去查彩虹表)。 预期解法是去patch程序输出,让程序能够输出check过的长度(即for循环中的i)。具体而言,这个循环是每次验证一位,不正确就退出循环,所以当我们的输入只有前3个字符正确的时候,i退出时应该是3;前4个字符正确的时候,i退出时应该是4。我们想办法让程序输出这个i,然后每一位去尝试每一个可见字符。i每自增一次,我们就知道当前这一位字符是正确的。当然了,这道题使用异常处理隐藏了真正的输出,真正的输出字符附在密文的最后,进行了一个异或0xff的解密之后才输出。,且加了反调试,如果是在调试状态下,不会进入异常,会进入假的print。

SEH异常处理机制

4

找到了异常处理函数,这个函数作用是打印flag,patch一下

5

还没成功,再研究一下