emojictf_wp

moshui Lv2

emoji ctf

最近是考试周,我就没报,但是网友发了我点题,就在空闲时间看了看

这个是题目,我只有除了签到以外的附件。

正片开始

emoji的兔子游戏

这个题我没看懂啥意思,莫名其妙就出来了

是个32位C++程序,简单读一下代码,嗯,很乱找找关键信息。

发现此处a即为心情存储的地方。根据题目提示,把心情改到4以下就行了。
我这边直接使用CE修改心情值为4以下即可,我由于害怕check_mem函数发现,ida挂了一下,下了个断点,不过发现没事。

拿到地址后,瞎改就行了

然后随便让他check一下,flag就出来了。

LFSR

打开一看,很短,加密函数一眼盯真。

继续看看,发现有个密钥生成。

基本确定流密码。想的是改一下寄存器,自动解密。但是此处有个坑,我总是解密不完全

我仔细看了一下,这个函数用strlen作为长度判断,遇到\x00自动停止

恰巧密文中有\x00,那只能手写了。

这波玩一个新的,试一下IchildYu师傅写的一个load-elf

脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//in x64_main.c
//...
// gcc ./x64_main.c -o main -g -ldl
int main() {

unsigned char result[43] = {
0x16, 0x54, 0xFD, 0x29, 0x5C, 0x23, 0xB1, 0xA1, 0x53, 0xD4, 0x3D, 0x4F, 0x2F, 0xA6, 0xF1, 0x53, 0xD2, 0xEC, 0x41, 0x82, 0xEE, 0xD5, 0x43, 0x16, 0xFC, 0x2F, 0x9E, 0xE7, 0x44, 0x00, 0x22, 0x3C, 0xB3, 0xF2, 0x50, 0x82, 0xBC, 0xDA, 0x46, 0xD8, 0xEA, 0x93, 0x00
};
const char* path = "/home/moshui/Desktop/lfsr";
void* base = load_elf(path);
short a = 0xACE1;
char (*get_key)(void*) = get_symbol_by_offset(base,0x1165);
char flag[42]="";
for ( int i = 0 ;i < 42; i++) {
flag[i] = result[i] ^ get_key(&a);
}

printf("%s",flag);
return 0;
}

C4

这个题的虚拟机其能在GitHub能找到C4 ,当然也给了提示说去GitHub看看。
我懒得逆向虚拟机,不过发现这玩意能单字节爆破


那就没啥意思了,直接开爆,脚本如下:

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
import subprocess
import string

def run_subprocess(char):
cmd = ['./c4', '-l', 'app']
process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)

stdout, stderr = process.communicate(input=char)

return stdout, stderr

def brute_force():
pre_char = ""
previous_cycle = 434 #初始值,就是第一个就错就是434
while True:
for char in string.printable:
stdout, stderr = run_subprocess(pre_char +char)

if stderr:
print(f"Error: {stderr}")
continue

if "exit(0) cycle =" in stdout:
cycle_value = int(stdout.split('cycle = ')[-1].strip())
if cycle_value > previous_cycle:
print(f"Correct character: {char}, Cycle value: {cycle_value}")
previous_cycle = cycle_value
pre_char += char
if(char == '}'):
print(pre_char)
raise Exception("correct")
else:
print(f"No cycle information found for character: {char}")

if __name__ == "__main__":
brute_force()

C4(fix)

一看竟然是把输出的cycle给删了。

难道没办法爆破了吗?那是不可能的,他给代码删了,不代表我们找不到了。既然他删了,那么我就改代码,让他输出出来。


简单分析一下(对比源码)就可以发现v87就是cycle,那么简单patch一下exit的输出就可以了。

这样就让第exit()的括号中输出cycle的值啦。

爆破脚本如下:

import subprocess
import string

def run_subprocess(char):
    cmd = ['./c4', '-l', 'app']
    process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               universal_newlines=True)
    
    stdout, stderr = process.communicate(input=char)
    
    return stdout, stderr

def brute_force():
    pre_char = ""
    previous_cycle = 434 #初始值,就是第一个就错就是434
    while True:
        for char in string.printable:
            stdout, stderr = run_subprocess(pre_char +char)
            
            if stderr:
                print(f"Error: {stderr}")
                continue
            
            if "exit(" in stdout:
                cycle_value = int(stdout.split('exit(')[-1].strip()[:-1])#就这里有变化其实,相当于是把)给过滤了
                if cycle_value > previous_cycle:
                    print(f"Correct character: {char}, Cycle value: {cycle_value}")
                    previous_cycle = cycle_value
                    pre_char += char
                    if(char == '}'):
                        print(pre_char)
                        raise Exception("correct")
            else:
                print(f"No cycle information found for character: {char}")

if __name__ == "__main__":
    brute_force()

  • 标题: emojictf_wp
  • 作者: moshui
  • 创建于 : 2024-06-16 18:51:17
  • 更新于 : 2024-06-17 00:38:32
  • 链接: https://www.moshui.eu.org/2024/06/16/emojictf-wp/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论