攻防世界-re部分题解(一)

攻防世界的题目质量还是比较高的,题目类型很多,难度也有一定的梯度,挺适合不断进阶学习。

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; // eax
unsigned int v4; // eax

puts("Reticulating splines, please wait..");
sleep(5u);
v3 = time(0);
srand(v3);
v4 = rand();
puts((&strs)[v4 % 0xA]);
return 0;
}

找到strs,其中flag

1
9447{This_is_a_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进制的形式输出

1
c0ffee

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)

输出结果

1
RC3-2016-XORISGUD

python-trade

见CG-CTF py交易

game

见BUGKU 游戏过关

hello-ctf

一串输入的字符串拷贝来拷贝去,实际上就是把输入的字符串变成16进制,所以直接从16进制转换成字符串就可以了

1
2
3
s = '437261636b4d654a757374466f7246756e'
flag = bytes.fromhex(s)
print(flag)

直接输出flag

1
CrackMeJustForFun

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进制转换位字符串然后逆序即可

1
DUTCTF{We1c0met0DUTCTF}

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]; // [rsp+10h] [rbp-70h]
char v4[32]; // [rsp+30h] [rbp-50h]
char v5[40]; // [rsp+50h] [rbp-30h]
int v6; // [rsp+78h] [rbp-8h]
int i; // [rsp+7Ch] [rbp-4h]

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为:

1
unctf{b66_6b6_66b}

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; // [rsp+14h] [rbp-24h]
const char *v3; // [rsp+18h] [rbp-20h]
const char *v4; // [rsp+20h] [rbp-18h]
const char *v5; // [rsp+28h] [rbp-10h]

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为:

1
Code_Talkers
攻防世界-re部分题解(二) 攻防世界-crackme-wp(手动脱壳)

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×