攻防世界RE-新手练习区

本文最后更新于:2021-11-26 下午

Hello CTF

详细分析

先查壳,看到无壳,可以直接打开。

使用IDA打开,可以看到我们输入的被转为十六进制最终存储在了v10之中,然后和v13比较,我们可以看到这部分的值是

437261636b4d654a757374466f7246756e

那么只需要将这部分十六进制值转为字符就行了,就是flag。

注册机

1
2
3
4
int main() {
unsigned char flag[] ="\x43\x72\x61\x63\x6b\x4d\x65\x4a\x75\x73\x74\x46\x6f\x72\x46\x75\x6e";
printf("%s", flag);
}

得到flag

CrackMeJustForFun

insanity

查看文件可以知道是32位的elf文件

使用IDA打开,看到非常简短的main函数,前面会生成一个随机数,然后可以看到str是个数组,生产的随机数除以0xA的余数作为下标,来决定puts函数输出什么。

看一下str数组,可以看到flag就在其中,第一个就是flag,当然如果运气好,随机数正好是0xA的倍数也可以自己输出flag。

9447{This_is_a_flag}

python-trade

详细分析

是一个pyc文件,在网上找一个反编译pyc的网站,查看反编译后的Python代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
import base64

def encode(message):
s = ''
for i in message:
x = ord(i) ^ 32
x = x + 16
s += chr(x)

return base64.b64encode(s)

correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
print 'correct'
else:
print 'wrong'

根据python代码写出注册机,算出flag

注册机

python

1
2
3
4
5
6
7
8
9
from base64 import *

flag = "XlNkVmtUI1MgXWBZXCFeKY+AaXNt"
flag = b64decode(flag)
s= ""
for i in flag:
i = (i - 16) ^ 32
s += chr(i)
print(s)

C

1
2
3
4
5
6
7
8
int main() {
unsigned char flag[] = "^SdVkT#S ]`Y\\!^)\x8f\x80ism";
for (int i = 0; i < 21; i++)
{
flag[i] = (flag[i] - 16) ^ 32;
}
printf("%s", flag);
}

nctf{d3c0mpil1n9_PyC}

re1

查壳,无壳,32位的程序

使用IDA打开分析,看到我们输入的值字符串会和v5.m128i_i8进行比较,查看其中的值

查看得到flag,注意这里是小端序

DUTCTF{We1c0met0DUTCTF}

game

详细分析

查壳,无壳

这是一个游戏,需要把所有的灯都点亮,才可以输出flag。

使用OD调试,搜索字符串可以看到flag成功输出的这里,只要能够运行到这里就可以了。

可以直接在函数头部右键,选择此处为新的EIP,然后直接跑起来,flag就会自己出来。

也可以修改之前的跳转条件,让程序可以运行到输出flag的地方。

注册机

使用IDA查看,可以看到如果满足所有的条件就会进入sub_457AB4

这是生成flag的地方,可以根据这里写出注册机。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
unsigned char v5[] = "\x12\x40\x62\x05\x02\x04\x06\x03\x06\x30\x31\x41\x20\x0C\x30\x41"
"\x1F\x4E\x3E\x20\x31\x20\x01\x39\x60\x03\x15\x09\x04\x3E\x03\x05"
"\x04\x01\x02\x03\x2C\x41\x4E\x20\x10\x61\x36\x10\x2C\x34\x20\x40"
"\x59\x2D\x20\x41\x0F\x22\x12\x10";
unsigned char v2[] = "\x7B\x20\x12\x62\x77\x6C\x41\x29\x7C\x50\x7D\x26\x7C\x6F\x4A\x31"
"\x53\x6C\x5E\x6C\x54\x06\x60\x53\x2C\x79\x68\x6E\x20\x5F\x75\x65"
"\x63\x7B\x7F\x77\x60\x30\x6B\x47\x5C\x1D\x51\x6B\x5A\x55\x40\x0C"
"\x2B\x4C\x56\x0D\x72\x01\x75\x7E";
for (int i = 0; i < 56; i++)
{
v2[i] = v2[i] ^ 0x13;
v2[i] = v2[i] ^ v5[i];
}
printf("%s", v2);
}

zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

open-source

打开题目是一个C的源代码

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
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
if (argc != 4) { //参数为4个
printf("what?\n");
exit(1);
}

unsigned int first = atoi(argv[1]);
if (first != 0xcafe) { //第一个参数atoi后为0xcafe、51966
printf("you are wrong, sorry.\n");
exit(2);
}

unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) {//第二个参数 除以5 余数不能是3,除以17余数要等于8
printf("ha, you won't get it!\n");
exit(3);
}

if (strcmp("h4cky0u", argv[3])) {
printf("so close, dude!\n"); //第三个参数,等于h4cky0u
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;
}

根据源码分析可以知道需要输入三个参数,三个参数满足条件后就会输出flag。

  • 第一个参数是51966
  • 第二个参数除以5 余数不能是3,除以17余数要等于8
  • 第三个参数,等于h4cky0u

根据条件求第二个参数,有很多,选择其中一个

python:

1
2
3
for i in range(1,100):
if(i % 5 != 3 and i % 17 == 8):
print(i)

得到flag

c0ffee

simple-unpack

查壳,可以看到是UPX的壳

直接使用upx-d脱壳

使用IDA打开,直接看到flag

flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}

logmein

详细分析

64位elf文件,无壳

使用IDA打开。可以明显的看到具体的比较地方,和flag生成的方式。&v7+i%v6,其中v6是7,也就是&v7+i%7,将v7转换为字符,一共就是七个,而i取7的余数,这里就是在不断的获取v7的每一位来与v8进行异或。

注册机

根据上面的分析写出注册机

1
2
3
4
5
6
7
8
9
10
int main() {
unsigned char a[] = "\x68\x61\x72\x61\x6D\x62\x65";
char flag[] = ":\"AL_RT^L*.?+6/46";
for (int i = 0; i < strlen(flag); i++)
{
flag[i] = flag[i] ^ (a[i % 7]);
}
printf("%s", flag);
return 0;
}

RC3-2016-XORISGUD

no-strings-attached

查壳,无壳,32位elf文件

使用IDA打开,分析发现关键函数是authenticate

看到输入被曝存在ws之中,然后wcscmp会比较s2和ws,s2是经过decrypt函数生成的。

查看具体的算法,看到是非常简单的减法。

数据为图中框起来的数据循环的减去1-5这几个数(因为都带着0x14,所以直接可以去掉0x14的)

注册机

1
2
3
4
5
6
7
8
9
10
11
int main() {
unsigned char s[] = "\x3A\x36\x37\x3B\x80\x7A\x71\x78\x63\x66\x73\x67\x62\x65\x73\x60\x6B\x71\x78"
"\x6A\x73\x70\x64\x78\x6E\x70\x70\x64\x70\x64\x6E\x7B\x76\x78\x6A\x73\x7B\x80";
int a[] = { 1,2,3,4,5 };
for (int i = 0; i < 38; i++)
{
s[i] -= a[i % 5];
}
printf("%s", s);
return 0;
}

9447{you_are_an_international_mystery}

getit

无壳,64位ELF文件

使用IDA打开,看到主要的流程是打开/tmp/flag.txt,然后向其中写入一些东西,但是最后又调用remove函数将其删除,所以是不可能查看flag.txt的,那么就看一下其写入的数据。看图中框选起来的部分可以看到,将s数组的每一位通过+1或者-1放在了t的十位以后的位置。

查看s与t

注册机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main() {
char flag[] = "c61b68366edeb7bdce3c6820314b7498";
int tmp = 0;
for (int i = 0; i < 32; i++)
{
if ((i & 1) != 0)
{
flag[i] += 1;
}
else
flag[i] -= 1;
}
printf("SharifCTF{%s}", flag);
return 0;
}

SharifCTF{b70c59275fcfa8aebf2d5911223c6589}

csaw2013reversing2

详细分析

查壳,无壳

直接运行程序,看到会弹出一个窗口,但是其中都是乱码根本不可读

使用IDA打开,看到lpMem就是那段乱码,正常流程都是弹窗显示这串字符,注意到sub_401000函数,其传入了参数lpMem

在其中对于lpMem进行了操作,可以看到主要是异或,并且四个字符作为一组来进行异或。

原始数据以及异或用的KEY

注册机

1
2
3
4
5
6
7
8
9
10
11
int main() {
unsigned char a[] = "\xBB\xAA\xCC\xDD";
unsigned char flag[] = "\xBB\xCC\xA0\xBC\xDC\xD1\xBE\xB8\xCD\xCF\xBE\xAE\xD2\xC4\xAB\x82\xD2\xD9\x93\xB3\xD4\xDE\x93\xA9\xD3\xCB\xB8\x82\xD3\xCB\xBE\xB9"
"\x9A\xD7\xCC\xDD";
for (int i = 0; i < 36; i++)
{
flag[i] = flag[i] ^ a[i%4];
printf("%c", flag[i]);
}
return 0;
}

flag{reversing_is_not_that_hard!}

maze

无壳,64位的elf文件

限制是必须是输入24位,前五位是“nctf{”,最后一位是“}”

看到最终成功的条件是,一系列操作之后asc_601060[8 * v9 + v10[0]]中的值正好等于”#”,

查看前面的流程,看到对于上面这个数组的位移来说,输入O是-1,o是+1,.是-8,0是+8

此数组,也就是说是一个8*8的迷宫,需要走到”#”的位置。

如图中这样的迷宫,这样走可以走到“#”,然后带入前面的几个走的字符,得到flag

nctf{o0oo00O000oooo..OO}


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!