攻防世界-re新手区wp

攻防世界-re新手区wp

https://adworld.xctf.org.cn/

文章目录

  • 攻防世界-re新手区wp
    • re1
    • ganme
    • hello,ctf
    • open-source
    • simple-unpack
    • logmein
    • insanity
    • no-strings-attached
      • 使用静态分析:
      • 使用动态调试:
    • csaw2013reversing2
    • gitit
    • python-trade
    • maze
  • 最后

re1

下载附件文件
使用exeinfope打开,32位无壳

使用ida打开
攻防世界-re新手区wp_第1张图片

发现是明文比较,并没有进行加密,然后看到最上面是赋值语句进入后看到字符串v5即为flag

在这里插入图片描述

ida使用小技巧,当光标移动到数据时,可以点击快捷键进行数据类型的转化,

a:将字符进行ascll编码,形成一个字符。

r:将一串数据转化为字符串,但要注意数据大小端的储存方式,这里形成的字符串时逆序的。

*:将数据组合形成数组。

u:消除对某段数据的分析,并呈现为十六进制数据。

c:将选中的数据分析为代码。

p:将选中的代码部分分析为一个函数。

d:转化选中的数据的数据类型,主要有Byte、Word、Dword

此处我们将转化好的数据放置到python中进行处理,直接倒序就可以得到flag

a = '0tem0c1eW{FTCTUD'[::-1]
b = '}FTCTUD'[::-1]
print(a+b)

在这里插入图片描述

ganme

使用exefope,32位无壳。

ida中分析,

攻防世界-re新手区wp_第2张图片

主函数主要有三部分组成,此处主演展示了后两部分。

第一部分为输出程序出现的界面,然后获取我们输入的n。

第二部分为游戏运行的过程,并重新绘制游戏界面。

第三部分为判定所有行是否已经全部合并,如果是那将进入一个子函数。

所以我们可以明确的看出程序关键的解密并输出flag的函数就是sub_457ab4()

攻防世界-re新手区wp_第3张图片

函数解密和输出部分如图示,其实就是一个简单的异或,但值得注意的是这是一种数组的写法:

其中的(&v2 + i)是表示地址偏移,是一种数组的写法,相当于v2[i],这是一种极为常见的写法。

所以我们可以直接根据这个函数写出脚本,注意将v2,v59写为数组就好。

但是这个函数负责将flag输出。
我们可以进行动态调试,并在此过程中控制if判定,最后让程序自己输出flag。

另外可以直接将游戏完成,输出flag。

还可以patch,使用ida将程序判定部分修改,然后输入一个值就可以判定为对,输出flag。

hello,ctf

攻防世界-re新手区wp_第4张图片

其中需要补充的函数:

sprintf:函数第一个参数为字符串,第二个是格式,第三个是数据,此函数的定义为:将某串数据以一种特定的格式形成一个字符串。

strcat:函数定义为字符串连接函数,将两个参量都是字符串,将参数二连接到参数一结尾。

所以我们可以简单的看出整个程序的算法就是将输入的flag转化为16进制,然后和与定义好的字符串v13比较,我们可以使用python2中的decode()方法:

在这里插入图片描述

open-source

附件是一份c的源代码,使用编辑器打开分析。

if (argc != 4) {
	printf("what?\n");
	exit(1);
}

这是其中的一小段,是极为典型的if配和!=判定,结构内部是错误的情况。一般我们可以通过这种地方的判定线索来确定有关于flag的信息。这个题目就是极为典型的。

这里我们可以将出现的几个值都以这样的形式得到,然后最后得到变量hash的值,得到其十六进制。

simple-unpack

使用exefope,upx壳64位。

使用upx进行脱壳:

攻防世界-re新手区wp_第5张图片

然后使用ida64打开,

然后发现main函数是铭文比较,直接得到flag。

logmein

查看,无壳64位。

攻防世界-re新手区wp_第6张图片

高亮的部分为错误,这里就再次出现了if判断的反向,我们可以知道flag和v8长度相同,v8v7异或就可以得到,但是要注意的是,v7的长度只有7个注意%7 且注意数据类型,v7在此处是Byte(相当于char )我们将其化为字符串,发现正好是七个,但是要注意大小端导致的倒序问题。

于是我们就可以使用python脚本得到flag了。

v7 = 'ebmarah'[::-1]
v8 = ":\"AL_RT^L*.?+6/46"
for i in range(len(v8)):
	print(chr(ord(v7[i % 7]) ^ ord(v8[i])),end='')

在这里插入图片描述

insanity

检查,无壳32位。

攻防世界-re新手区wp_第7张图片

可以直接字符串搜索出来,ida中快捷键SHIFT+F12

另外在Linux下直接运行也可以得到flag,./+文件名。

no-strings-attached

检查,无壳32位。

攻防世界-re新手区wp_第8张图片

main函数极为简单,其中观察后我们轻易的知道,关键函数应该是在authenticate()中,

攻防世界-re新手区wp_第9张图片

发现加密函数`decrypt()`

攻防世界-re新手区wp_第10张图片

使用静态分析:

我们使用idapy脚本将传入decrypt() 的两个参数打印出来:

我们可以通过使用*指令的时候看到数组的大小,一般再根据数据进行调整。

addr=0x8048a90 #数组的地址
arr=[]
for i  in range(6): #数组的个数
    arr.append(Dword(addr+4*i))
print(arr)

然后我们打印出两个数组,舍掉每个数组最后出现的0,然后根据加密函数操作。

a2 = [5121, 5122, 5123, 5124, 5125]
dest = [5178, 5174, 5175, 5179, 5248, 5242, 5233, 5240, 5219, 5222, 5235, 5223, 5218, 5221, 5235, 5216, 5227, 5233, 5240, 5226, 5235, 5232, 5220, 5240, 5230, 5232, 5232, 5220, 5232, 5220, 5230, 5243, 5238, 5240, 5226, 5235, 5243, 5248]
i = j = 0
while i < 38:
	j = 0
	while j <5 and i < 38:
		dest[i] -= a2[j]
		i += 1
		j += 1
for i in range(38):
	print (chr(dest[i]),end='')
	i += 1

在这里插入图片描述

使用动态调试:

将程序放置到linux环境下,使用gdb调试程序

gdb ./xxxxxx -q  #使用gdb打开程序进行调试
start            #开始进行调试
n                #单步步过
s                #单步步入
x/6sw $eax       #显示六行数据/以字符串形式/word形式/查看eax中的值。

攻防世界-re新手区wp_第11张图片

csaw2013reversing2

攻防世界-re新手区wp_第12张图片

观察main函数,其中调用的子函数除了windowsapi,就只有两个函数,其中有一个还是最开始调用,所以关键的能使flag不乱码的函数应该是在sub_401000中。

另外观察到函数前调用了apiIsDebuggerPresent,这个函数用于检测该程序是否处于dedug状态,即是否被调试。

另外我们通过对apiMessageBoxA的分析可知,我们显示乱码的字符串,即flag应该是局部变量`[ebp+lpMem]。

在动态调试过程中,控制程序执行到sub_401000位置,然后注意前面的int 3干扰数据可以nop掉,然后关注mov指令是将局部变量的地址赋值给edx,此时就可以查到字符串的地址,进行call,调用完函数以后就可以看到字符串的值改变,成为了flag。
攻防世界-re新手区wp_第13张图片
攻防世界-re新手区wp_第14张图片

gitit

检查,无壳64位。

攻防世界-re新手区wp_第15张图片

main函数后面主要为文件处理部分,前面是重要的flag处理函数。

可以得到s和t的值

攻防世界-re新手区wp_第16张图片

然后写出脚本:

#SharifCTF{????????????????????????????????}
s = 'c61b68366edeb7bdce3c6820314b7498'
for v5 in range(len(s)):
	v3 = -1
	if v5 & 1:
		v3 = 1
	print(chr(ord(s[v5]) + v3),end='')

然后得到字符串替换掉?的内容即可。

python-trade

得到一个.pyc文件,使用[在线编辑器][http://tools.bugscaner.com/decompyle/] 打开形成.py文件:

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'

关键部分就是逆向出for循环中的算法即可:

import base64
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
a = base64.b64decode(correct)
flag = ''
for i in range(len(a)):
	x = a[i]
	x -= 16
	y = x ^ 32
	flag += chr(y)
print(flag)

攻防世界-re新手区wp_第17张图片

maze

检查,无壳64位。且题目提示这是迷宫题。

ida伪代码是一个多重跳转的复杂结构:
攻防世界-re新手区wp_第18张图片
所以我们直接看汇编代码的结构图:

攻防世界-re新手区wp_第19张图片

然后我们发现中间的判定是关于输入的字符,然后调整寄存器r14r15 最后回到大的区块上,使用sub_400690 函数处理,我们进入发现是迷宫的判定。

攻防世界-re新手区wp_第20张图片

然后发现*8的就是上下,另一个是左右,可以定位到r14r15 然后我们可以确定四个字符分别代表的上下左右,而且也可以看出,是8行的迷宫。我们可以看到那个字符串,直接将他打印出来:

攻防世界-re新手区wp_第21张图片
然后我们看到最开始是在(0,0)的位置,要走到#才算成功,就可以得到行走的字符串,然后在这里插入图片描述再套上格式就是flag了。

最后

现在刚整理完gdb那一段,所以完整的发博客了。
因为是之前整理的,其中大部分脚本使用sublime+cmd运行的python。后来才知道配置编辑器插件,sublime/vscode都可以跑程序还是很香。

你可能感兴趣的:(题目的整理,逆向)