攻防世界的题目质量还是比较高的,题目类型很多,难度也有一定的梯度,挺适合不断进阶学习。
insanity
IDA打开,进入main,发现程序在生成随机数,然后随便输出一系列字符串中的某一个,找到这一系列字符串,发现了flag
1 2 3 4 5 6 7 8 9 10 11 12 13
| int __cdecl main(int argc, const char **argv, const char **envp) { unsigned int v3; unsigned int v4;
puts("Reticulating splines, please wait.."); sleep(5u); v3 = time(0); srand(v3); v4 = rand(); puts((&strs)[v4 % 0xA]); return 0; }
|
找到strs,其中flag
open-source
这题真就连源代码都给了
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
| #include <stdio.h> #include <string.h>
int main(int argc, char *argv[]) { if (argc != 4) { printf("what?\n"); exit(1); }
unsigned int first = atoi(argv[1]); if (first != 0xcafe) { printf("you are wrong, sorry.\n"); exit(2); }
unsigned int second = atoi(argv[2]); if (second % 5 == 3 || second % 17 != 8) { printf("ha, you won't get it!\n"); exit(3); }
if (strcmp("h4cky0u", argv[3])) { printf("so close, dude!\n"); exit(4); }
printf("Brr wrrr grr\n");
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
printf("Get your key: "); printf("%x\n", hash); return 0; }
|
看一下源码,发现运行时要有三个参数,第一个参数给出来了,是0xcafe,第二个没有给,但是知道second%17==8,直接带到下面计算就行了,第三个是字符串的长度,为7,直接算出来就行了。
不过还需要注意,最后输出的时候是以16进制的形式输出
simple-unpack
题如其名,拿到直接upx脱壳,毫无阻碍,IDA打开直接在main里看到flag
1
| flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}
|
logmein
IDA打开,找到关键判断位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| strcpy(v8, ":\"AL_RT^L*.?+6/46"); v7 = 'ebmarah'; v6 = 7; printf("Welcome to the RC3 secure password guesser.\n", a2, a3); printf("To continue, you must enter the correct password.\n"); printf("Enter your guess: "); __isoc99_scanf("%32s", s); v3 = strlen(s); if ( v3 < strlen(v8) ) sub_4007C0(v8); for ( i = 0; i < strlen(s); ++i ) { if ( i >= strlen(v8) ) ((void (*)(void))sub_4007C0)(); if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) ) ((void (*)(void))sub_4007C0)(); }
|
v7本身是一个长整型,但是作为字符读取,由于小端序,所以转换成的字符要反序,然后经过下面的计算就可以了
1 2 3 4 5 6
| v8 = ':\"AL_RT^L*.?+6/46' v7 = 'harambe' s = '' for i in range(len(v8)): s += chr(ord(v7[i % 7]) ^ ord(v8[i])) print(s)
|
输出结果
python-trade
见CG-CTF py交易
game
见BUGKU 游戏过关
hello-ctf
一串输入的字符串拷贝来拷贝去,实际上就是把输入的字符串变成16进制,所以直接从16进制转换成字符串就可以了
1 2 3
| s = '437261636b4d654a757374466f7246756e' flag = bytes.fromhex(s) print(flag)
|
直接输出flag
getit
同样是一道简单题,写个简单的逆运算就可以了
1 2 3 4 5 6 7 8 9 10 11 12
| s = 'c61b68366edeb7bdce3c6820314b7498' t = '' v5 = 0 while (v5 < len(s)): if (v5 & 1): v3 = 1 else: v3 = -1 t += chr(ord(s[v5]) + v3) v5 = v5 + 1 t='SharifCTF{'+t+'}' print(t)
|
输出flag
1
| SharifCTF{b70c59275fcfa8aebf2d5911223c6589}
|
re1
IDA打开追踪字符串,发现flag和输入直接进行比较,找到flag的位置,然后将16进制转换位字符串然后逆序即可
no-strings-attached
这题有点意思,整个程序没有直接出现的字符串,先打开IDA看看,找到一个decrypt函数,一看就知道这个是最重要的部分,又不想再写脚本去算,所以干脆开虚拟机gdb动态调试,在decrypt处下断点,等运行完decrypt函数之后,发现程序把某个地址拷进了eax,所以用x/6sw $eax
来查看,结果发现了flag
1
| 9447{you_are_an_international_mystery}
|
csaw2013reversing3
这题比较有意思,一打开输出的是乱码,用IDA打开发现这些代码没有解密,有一个解密程序但是没有运行,所以OD直接调试改汇编,先运行解密函数,然后跳转到MessageBoxA函数,在窗口中输出来的就是真正的flag,操作比较简单,就不赘述了。
1
| flag{reversing_is_not_that_hard!}
|
maze
见CG-CTF maze
666
IDA打开看到了假flag,不管它,找到关键函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| int __fastcall encode(const char *a1, __int64 a2) { char v3[32]; char v4[32]; char v5[40]; int v6; int i;
i = 0; v6 = 0; if ( strlen(a1) != key ) return puts("Your Length is Wrong"); for ( i = 0; i < key; i += 3 ) { v5[i] = key ^ (a1[i] + 6); v4[i + 1] = (a1[i + 1] - 6) ^ key; v3[i + 2] = a1[i + 2] ^ 6 ^ key; *(_BYTE *)(a2 + i) = v5[i]; *(_BYTE *)(a2 + i + 1LL) = v4[i + 1]; *(_BYTE *)(a2 + i + 2LL) = v3[i + 2]; } return a2; }
|
这里进行了一些运算,运算的结果要和一个已经定义的enflag字符串相同,所以很好逆,这里需要注意运算顺序,异或运算加括号,不然会先计算加减
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <iostream> #include <cstring> #include <string> using namespace std; int main() { int key = 0x12; unsigned char a2[] = { 0x69, 0x7A, 0x77, 0x68, 0x72, 0x6F, 0x7A, 0x22, 0x22, 0x77, 0x22, 0x76, 0x2E, 0x4B, 0x22, 0x2E, 0x4E, 0x69 }; char a1[key+1]; for (int i = 0; i < key; i += 3 ) { a1[i]=(a2[i]^key)-6; a1[i+1]=(a2[i+1]^key)+6; a1[i+2]=a2[i+2]^key^6; } cout<<a1<<endl; return 0; }
|
输出的flag为:
Reversing-x64Elf-100
没什么难度,找到关键函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| signed __int64 __fastcall sub_4006FD(__int64 a1) { signed int i; const char *v3; const char *v4; const char *v5;
v3 = "Dufhbmf"; v4 = "pG`imos"; v5 = "ewUglpt"; for ( i = 0; i <= 11; ++i ) { if ( (&v3)[i % 3][2 * (i / 3)] - *(char *)(i + a1) != 1 ) return 1LL; } return 0LL; }
|
a1就是我们需要的flag了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <iostream> #include <cstring> #include <string>
using namespace std;
int main() { char v3[3][8] = {"Dufhbmf", "pG`imos", "ewUglpt"}; char a1[13]; for (int i = 0; i <= 11; ++i) { a1[i] = v3[i % 3][2 * (i / 3)] - 1; } cout<<a1<<endl; return 0; }
|
输出的flag为:
Comments