REVERSE-PRACTICE-BUUCTF-12
- [WUSTCTF2020]level3
- crackMe
- [FlareOn6]Overlong
- [WUSTCTF2020]Cr0ssfun
[WUSTCTF2020]level3
elf文件,无壳,ida分析
main函数中,获取输入,对输入做base64编码,提示有错误,在程序中有一个奇怪的字符串,提示和标准base64不同,估计是变表base64
进入base64_encode函数,正常的base64编码逻辑,对base64_table交叉引用,发现在O_OLookAtYou函数中也有对base64_table的引用
进入O_OLookAtYou函数,果然是对base64_table的变换
之前也遇到过变表base64的题目,见REVERSE-PRACTICE-BUUCTF-7
直接拿脚本来用了,执行脚本即可得到flag
#coding:utf-8
#base="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 原表
base=[0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64,0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,0x38, 0x39, 0x2B, 0x2F] #原表的ascii码表示,方便进行原表变换
#对原表进行变换
for i in range(0,10):base[i],base[19-i]=base[19-i],base[i]
#base_changed是变表,需要转成字符串的形式
base_changed=''.join(chr(i) for i in base)
print("Current Base:\n%s " %base_changed) #打印base_changed变表
def base64_decode(inputs): #inputs是base64字符串# 将字符串转化为2进制bin_str = []for i in inputs:if i != '=':x = str(bin(base_changed.index(i))).replace('0b', '')bin_str.append('{:0>6}'.format(x))# 输出的字符串outputs = ""nums = inputs.count('=')while bin_str:temp_list = bin_str[:4]temp_str = "".join(temp_list)# 补足8位字节if (len(temp_str) % 8 != 0):temp_str = temp_str[0:-1 * nums * 2]# 将四个6字节的二进制转换为三个字符for i in range(0, int(len(temp_str) / 8)):outputs += chr(int(temp_str[i * 8:(i + 1) * 8], 2))bin_str = bin_str[4:]print("Decoded String:\n%s " % outputs)
#enc是经变表base64编码的字符串
enc="d2G0ZjLwHjS7DmOzZAY0X2lzX3CoZV9zdNOydO9vZl9yZXZlcnGlfD=="
base64_decode(enc)
运行结果
crackMe
exe程序,运行后输入用户名welcomebeijing和密码,输入错误要重新输入,无壳,ida分析
在wmain函数中,获取输入的user和password并检验长度且均为数字或字母,在sub_401090函数中,由输入的user(welcomebeijing)生成了一个固定的table,这个table在下面的check函数中也有引用
sub_4011A0函数是个传入的两个参数赋值,第一个参数赋为"Congratulations",第二个参数赋为"please try again",由check函数的返回结果决定输出
进入check函数
先看第一个while循环体,在该循环体中,v15被赋值,而且v15在下一个循环体中有引用,经调试可知,该循环体实际是将pwd的内容两两分组,每两个字符组成一个十六进制数放入v15中,例如,输入的pwd为0123456789abcdef,v15的元素为0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF
接着看第二个循环体,v15实际就是输入的pwd,要和table的元素异或,存入v17,而table的元素由v8和v13决定,v8和v13又由v11和v12决定,可以看到,在异或运算的上下,有两条判断当前是否处于调试状态的if语句,如果是调试状态,则会修改v13,v11,v12的值,也就是说,有两个地方存在反调试,但我们并不知道进行异或运算的table的元素到底是什么,由之前的分析可知,table的全部元素是由输入的user确定的,于是可以通过调试获知进行异或运算的table的元素,因此需要把反调试的两条语句nop掉或修改跳转逻辑,使在调试状态下,不执行if成立的语句
下图为修改跳转逻辑,将.text:00CA1AE8和.text:00CA1B5E两处指令的jz改成jnz,就实现了调试状态下,不执行if成立的语句,注意修改跳转逻辑后要应用到可执行程序exe
下图为修改跳转逻辑后的效果,再往下走,sub_CA1710函数是对v17和user(welcomebeijing)进行异或,while循环体结束后,sub_CA1470函数是对v17的验证,v17在经过一系列运算后的结果应为"dbappsec",长度为8
写脚本前需要先通过调试得到与v15进行异或运算的8个table的元素,为[0x2a,0xd7,0x92,0xe9,0x53,0xe2,0xc4,0xcd],写脚本,提交第二个md5值成功
[FlareOn6]Overlong
exe程序,运行后提示说没有破坏编码,冒号后面没有内容,无壳,ida分析
start函数,unk_402008作为参数传入了sub_401160函数参与运算,运算长度为第三个参数28,运算结果放入Text中,最后通过MessageBoxA将Text的内容输出
sub_401160函数以及sub_401000函数是程序写好的运算逻辑,由提示可知运算逻辑不会变,加上overlong的提示,应该是让参与运算的元素更多,即sub_401160函数的第三个参数更大,让程序运算输出flag
当修改参与运算长度28为72时,应用到程序并运行,得到flag
[WUSTCTF2020]Cr0ssfun
elf文件,无壳,ida分析
main函数逻辑清晰,获取输入,调用check检验输入,check返回1时说明输入正确
进入check函数,是对输入input内容的直接判断,其余的函数同理
写脚本即可得到flag