攻防世界新手Re

攻防世界Re新手区

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
#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) {//得出first=0xcafe转换成10进值为51966
printf("you are wrong, sorry.\n");
exit(2);
}
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) {//second=25
printf("ha, you won't get it!\n");
exit(3);
}
if (strcmp("h4cky0u", argv[3])) {//argv[3]=’h4cky0u’
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;
}

然后直接写出脚本

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <string.h>
int main () {
unsigned int first = 51966;
unsigned int second=25;
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen("h4cky0u") - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}

image-20210723204529916

game

法一:直接运行看到是image-20210717111904925

类似数学?随便按1~8顺序按了一下,神奇的事情发生了。。。一脸懵逼,很突然的我也不知道原理

image-20210717111847983

法二:其实考点是算法

拖IDA,先找字符串发现没东西,然后main,f5

image-20210717131544368

似乎没东西,找看起来有东西的函数

image-20210717131604221

很明显调用了东西,点进去康康发现flag字眼

image-20210717131653612

他是一直到image-20210717131735829

重点是循环语句那段

1
2
3
4
5
6
7
 for ( i = 0; i < 56; ++i )
{
*(&v2 + i) ^= *(&v59 + i);//异或运算
*(&v2 + i) ^= 0x13u;
}
return sub_45A7BE((int)"%s\n");
}
1
2
3
4
5
6
7
8
a= [18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0]
b=[123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0]
flag = ''
for i in range(56):
a[i] = a[i]^b[i]
a[i] = a[i]^19#按R转换上文字符等于19
flag+=chr(a[i])
print(flag)

image-20210717133351831

Hello,CTF

先跑程序

image-20210717134157670

要输入啥的不知道,肯定是flag。拖IDA梭哈image-20210717134226130

strcpy(&v13, "437261636b4d654a757374466f7246756e");

明显flag就是他。。一个16进制码(数字09和字母AF),直接转码

image-20210717134433247

simple-unpack

考点:脱壳

从题目已知这个是加壳文件,工具先查一下壳

image-20210717135043548

下面的信息显示64bit知道是64位文件,upx知道是upx加壳

那就直接脱掉

image-20210717135954434

然后拖入IDA

image-20210717140107815

映入眼帘。

法二:自己脱壳做出来后,网上说这个不用脱壳。。。直接拖入010一查就有。。像个misc似的

image-20210717140929475

logmein

拖入IDA,main F5

image-20210717143821052

先将v7按R变成字符image-20210717153702029然后倒过来取,即

v7=harambe,然后v8肯定是加密后的flag了

重点是循环语句

1
2
3
4
5
6
7
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)();
}

脚本

1
2
3
4
5
6
7
a='harambe'
b=':\"AL_RT^L*.?+6/46'
flag = ''
for i in range(len(b)):
c = ord(a[i%7])^ord(b[i])
flag+=chr(c)
print(flag)

image-20210718192554946

ord()函数是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常。

no-strings-attached

先查知道是32位ELF,再IDA

image-20210717155525760

觉得最后一个函数里有东西,点进去

image-20210717160318691

发现了一个看起来似乎很关键的函数decrypt,点进去看到image-20210717160100419

很明显返回的dest里有flag,而s和a2里面或许有dest相关的东西。但是看了半天点了半天没东西,直接看wp

回去看汇编

image-20210717161812007

通过汇编代码,了解到eax保存dest的值后传递给s2

不需要去分析decrypt的内容了,直接上gdb动态调试。

gdb动态调试指令:

下断点:

1
b *地址

由IDA看出decrypt的地址

image-20210717174017012

所以在他下一行加个断点

image-20210717174057614

image-20210717174226983

执行到断点所在位置

1
r

image-20210717174301145

单步跟踪:

1
n

由于直接下断点在他的下一行所以不用跟了

查看寄存器保存的内容:

1
i r

image-20210717174353300

查看内存地址(寄存器)中的值:

1
x/5sw $eax

参数含义:
x:examine–>检测内存地址中保存的值
5:显示5行目标数据
s:以字符串形式打印
w:以双字打印

image-20210717174414940

getit

查,IDA一把梭

image-20210717181731840

好像没什么特别的

重点看循环

1
2
3
4
5
6
7
8
9
10
while ( (signed int)v5 < strlen(s) )
{
if ( v5 & 1 )
v3 = 1;
else
v3 = -1;
*(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;
LODWORD(v5) = v5 + 1;
}
strcpy(filename, "/tmp/flag.txt");

好像也没看出什么,也没给s是啥。点了其他的函数也没东西,看wp。。。。

玄机在s里,点进去就看见了(好家伙,原来字符串是给的呀。。)

image-20210717182011419

然后对照伪代码写出脚本就行了

1
2
3
4
5
6
7
8
9
a = 'c61b68366edeb7bdce3c6820314b7498'
flag = ''
for i in range(len(a)):
if i&1:
x=1
else:
x=-1
flag+=chr(ord(a[i])+x)
print(flag)

image-20210717183900450

python-trade

下载下来得到pyc文件,需要经过反编译得出原py文件

python反编译 - 在线工具 (tool.lu)

py是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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"

很明显,中间那段是加密代码

利用加密后的明文和加密代码往前推,写出解密代码

1
2
3
4
5
6
7
8
9
10
import base64

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

image-20210717202211618

csaw2013

可执行文件先打开

image-20210718201249537

乱码。肯定无别的

然后照例查后得知是32位,可以用OD打开

image-20210718201405267

先用IDA看看有些什么

image-20210718201459667

看到flag字眼,搞了一套没发现东西,它前面的lpMem似乎与Flag有东西。

image-20210718201649763

结果无。然后分析一下特殊语段if

image-20210718202224765

看出来if语句有个退出的函数,而它有弹出框,所以if语句并没有执行

然后好像就看着没什么东西了。打开OD

image-20210718202514589

没什么头绪,往上随便翻翻看旁边注释注意到了Flag

image-20210718202635361

思路很清晰,肯定是从这里开始入手改东西让它这个弹出框显示不是乱码的窗体得到flag,也就是去让它执行那个if语句。

这个jmp指令跳转到第二个MessageBox处就行了image-20210718203254689

因为可以看到它原来是直接跳过了两个文本框,所以不执行if语句。

image-20210718203545263

然后改这个。但是运行起来是不行的,然后人麻了。再看看就发现image-20210718203706001

这有个je指令先跳了,得先把它变成空操作指令nop,还有个int3下了断点,所以也先变成nop

image-20210718204242092

然后直接运行就有了

image-20210718204312647

maze

一套操作下来根本就没有头绪,直接看wp是迷宫问题](https://ctf-wiki.github.io/ctf-wiki/reverse/maze/maze/)

输入的是’.’,’0’,’o’,’O’,并以此来确定上下左右移动

img

从这里可以看出先是进行判断,如果满足则进入判断,开头必须是以nctf{开头的

然后往下分析

img

从这里可以看出进行了四个判断,然后,进入四个函数()

img

img

img

img

从上往下以此追踪,可以发现这些函数会跳到lable15的位置,然后,对lable15分析,发现特殊的字符串

img

然后,猜测可能是一个8*8的迷宫

img

走过迷宫,获得flag:nctf{o0oo00O000oooo..OO}