近期解题 2024.3.14
文章目录
[SWPU2019] ReverseMe
乍一看 main()
函数里没有什么东西。切到反汇编界面,我们看到了一位老朋友——SEH。
通过使用“广撒网”的打断点方式(在每一个可疑的 call
指令打断点),找到输入函数的位置:
紧接着下面就对输入内容的长度进行判定,输入内容的长度为 0x20。
继续调试,可以看到输入的内容在下面位置进行了异或操作:
最后在下面与密文进行比较:
根据此操作的特点,流程图模式中指向自己的代码块更可能是执行加密算法的部分。
提取数据后使用脚本解密:
1k1 = 'SWPU_2019_CTF'
2k2 = [
3 0x86, 0x0C, 0x3E, 0xCA, 0x98, 0xD7, 0xAE, 0x19, 0xE2, 0x77,
4 0x6B, 0xA6, 0x6A, 0xA1, 0x77, 0xB0, 0x69, 0x91, 0x37, 0x05,
5 0x7A, 0xF9, 0x7B, 0x30, 0x43, 0x5A, 0x4B, 0x10, 0x86, 0x7D,
6 0xD4, 0x28
7]
8k3 = [
9 0xB3, 0x37, 0x0F, 0xF8, 0xBC, 0xBC, 0xAE, 0x5D, 0xBA, 0x5A,
10 0x4D, 0x86, 0x44, 0x97, 0x62, 0xD3, 0x4F, 0xBA, 0x24, 0x16,
11 0x0B, 0x9F, 0x72, 0x1A, 0x65, 0x68, 0x6D, 0x26, 0xBA, 0x6B,
12 0xC8, 0x67
13]
14
15for i in range(0x20):
16 print(chr(ord(k1[i % 13]) ^ k2[i] ^ k3[i]), end = '')
17
18# output: flag{Y0uaretheB3st!#@_VirtualCC}
buuctf - rsa
不是很懂,为什么一道 RSA 被放到了逆向里。
题目附件中有两个文件: pub.key
和 flag.enc
。
万事俱备,直接解:
1from Crypto.PublicKey import RSA
2
3with open('pub.key', 'r') as pubkey:
4 key = RSA.importKey(pubkey.read())
5
6print(key.n)
7
8# output: 86934482296048119190666062003494800588905656017203025617216654058378322103517
上面的脚本从 pub.key
中读取出了 n
,分解后可以解出 flag:
1from Crypto.Util.number import *
2import gmpy2
3
4n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
5p = 285960468890451637935629440372639283459
6q = 304008741604601924494328155975272418463
7e = 65537
8
9phi = (p - 1) * (q - 1)
10d = gmpy2.invert(e, phi)
11
12with open('flag.enc', 'rb') as flag:
13 c = bytes_to_long(flag.read())
14
15m = pow(c, d, n)
16print(long_to_bytes(m))
17
18# output: b'\x02\x9d {zR\x1e\x08\xe4\xe6\x18\x06\x00flag{decrypt_256}\n'
[QCTF2018] Xman-babymips
题目唯一亮点在于它是 MIPS 架构汇编,不过用 IDA 7.7 照样可以反编译。
核心代码:
1int __fastcall main(int a1, char **a2, char **a3)
2{
3 int i; // [sp+18h] [+18h] BYREF
4 char v5[36]; // [sp+1Ch] [+1Ch] BYREF
5
6 setbuf(stdout, 0);
7 setbuf(stdin, 0);
8 printf("Give me your flag:");
9 scanf("%32s", v5);
10 for ( i = 0; i < 32; ++i )
11 v5[i] ^= 32 - i;
12 if ( !strncmp(v5, fdata, 5u) )
13 return sub_4007F0(v5);
14 else
15 return puts("Wrong");
16}
17
18int __fastcall sub_4007F0(const char *a1)
19{
20 char v1; // $v1
21 size_t i; // [sp+18h] [+18h]
22
23 for ( i = 5; i < strlen(a1); ++i )
24 {
25 if ( (i & 1) != 0 )
26 v1 = (a1[i] >> 2) | (a1[i] << 6);
27 else
28 v1 = (4 * a1[i]) | (a1[i] >> 6);
29 a1[i] = v1;
30 }
31 if ( !strncmp(a1 + 5, off_410D04, 0x1Bu) )
32 return puts("Right!");
33 else
34 return puts("Wrong!");
35}
我 NT 了,竟然在这道题上卡住,主要是脚本写的有问题。正确脚本如下:
1c = [
2 0x51, 0x7C, 0x6A, 0x7B, 0x67, 0x52, 0xFD,
3 0x16, 0xA4, 0x89, 0xBD, 0x92, 0x80, 0x13, 0x41, 0x54, 0xA0,
4 0x8D, 0x45, 0x18, 0x81, 0xDE, 0xFC, 0x95, 0xF0, 0x16, 0x79,
5 0x1A, 0x15, 0x5B, 0x75, 0x1F
6]
7
8for i in range(5, 32):
9 if i % 2 == 0:
10 c[i] = (c[i] >> 2 | c[i] << 6) & 0x7F
11 else:
12 c[i] = (c[i] << 2 | c[i] >> 6) & 0x7F
13
14for i in range(32):
15 print(chr(c[i] ^ 32 - i), end = '')
16
17# output: qctf{ReA11y_4_B@89_mlp5_4_XmAn_}
[WMCTF2020] easy_re
这道题的程序使用 Perl 语言编写,随后通过 ActivePerl 将代码打包成可执行文件。运行程序,程序会输出 "please input the flag:" 提示输入 flag。但是在 IDA 中搜索字符串,无法找到相应字符串。
根据已知的信息,Perl 语言在打包成可执行文件时,会将解释器、编译器与压缩后的代码一同装进可执行文件中。在执行时,程序会首先初始化编译器,随后解压代码并执行代码。在执行源代码,程序会向栈内压入一个字符串 "script" 用于标记。因此搜索字符串 "script" 并定位到这里。
上图中 sub_40D1A0()
是解压 Perl 脚本的部分,解压完成后原始 Perl 脚本地址会存储在 rax
寄存器中。
经调试可以得到原始 Perl 脚本:
1$flag = "WMCTF{I_WAnt_dynam1c_F1ag}";
2print "please input the flag:";
3$line = <STDIN>;
4chomp($line);
5if($line eq $flag){
6 print "congratulation!"
7}else{
8 print "no,wrong"
9}
flag 一目了然。