Buuctf-reverse
新年快乐exeinfo pe的使用
查壳发现有upx壳,那么脱壳是什么呢?
用upx脱壳工具(https://github.com/upx/upx/releases)
进行脱壳,语句为upx -d +文件路径
脱壳成功
用ida打开
分析代码可知,strcpy函数是将字符串复制给Str2。而if( !strncmp(Str1, Str2, strlen(Str2)) )语句是判断Str1和Str2这两个字符串的字符是否相等,长度为Str2字符串的长度。所以只要找到Str1和Str2中任意一个就可以知道flag了
xor
分析源代码
这里最重要的是strncmp函数,strncmp(__b, global, 0x21uLL)比较了__b和global两个字符串的前0x21uLL(也就是33)个字符。如果这两个字符串的前33个字符相同,strncmp函数将返回0。也就是说,将global所对应的值逆向操作,就能得到flag了
双击global,得到了字符串aFKWOXZUPFVMDGH,这个字符串对应的ascll码,进行逆向操作就是flag
运行python脚本得到flag
a = [102,10,107,12,119,38,79,46,64,17,120,13,90,59,85,17,112,25,70,31,118,34,77,35,68,14,103,6,104,15,71,50,79,0]
b= [0]*33
b[0]=a[0]
for i in range(1,33 ):
b[i]= a[i] ^ a[i - 1]
for i in range(33):
print(chr(b[i]),end='')
reverse3
分析源码,找出Destination或者Str2的值,就能得出flag
这里的for循环改了Destination的值,可以写脚本把str2逆向回去,得到e2lfbDB2ZV95b3V9
a = [101,51,110,105,102,73,72,57,98,95,67,64,110,64,100,72,0]
b = [0]*len(a)
for i in range(0,16):
b[i] = a[i] - i
print(chr(b[i]),end='')
print(b)
提交发现并不是flag,继续往上看代码。strncpy函数的作用是从v4字符串复制最多40个字符到Destination中,也就是说v4也会改变Destination的值
v4 =sub_4110BE(Str,v3,v14),v4的值又由sub_4110BE函数决定。根据sub_4110BE函数源代码,发现这个函数的作用是对输入的东西进行base+64编码
所以把e2lfbDB2ZV95b3V9进行base64编码即可得到flag
SimpleRev
首先引入一个概念:大端字节序big endian 小端字节序little endian 中英字幕x精译搬运字节次序 - 位序和字节序 大端序 小端序
由die可知,本题文件字节序为LE,是小端序
分析main函数,第二个if语句puts("Input fault format!"),看起来flag跟这里没什么关系。看另一个if语句,有一个没定义的Decry函数,双击查看源代码
看到flag,这个函数就是解题关键了
观察末尾if语句可知,本题要找到text或者是str2
join函数功能是将多个字符串连接起来,这里的v9是经历了一个转为ascll码的过程,v9转化为ascll码是wodah。我们可能会误以为text = killswodah。当v9转化为ascll码并存储时,由于是小端序,高位字节会被存到高地址位中,v9存储到内存中是hadow。计算机对数据的读写是从低地址位向高地址位读取,执行了join函数后text = killshadow
ctrcat函数会把key和src连接。同理,key = ADSFKNDCLS
分析后面的源代码
v3=0 ADSFKNDCLS=key=src v9=hadow v5=10 v2=0 v1=0 text = killshadow
for(i = 0; i < 10; ++i){
if( key[v3 % 10] > '@' && key[v3 % 10] <= 'Z')
key[i] = key[v3 % 10] + 32;
++v3; #检测key[0-9]是否是大写,如果是大写就+32,也就是变成小写
}
printf("Please input your flag:");
while ( 1 )
{
v1 = getchar();
if ( v1 == '\n' )
break;
if ( v1 == ' ' ) #读取一个字符,如果是回车就跳出循环
{
++v2; #如果是空格,v2+1
}
else
{
if ( v1 <= '`' || v1 > 'z' ) # 如果不是小写
{
if ( v1 > '@' && v1 <= 'Z' ) # 如果是大写就执行下面代码
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97; # 算是一个加密混淆过程
++v3;
}
}
else # 如果是别的符号,执行下面代码
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
if ( !(v3 % v5) ) # 如果v3能整除v5,打印一个空格
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) ) # 如果text=str2,得到flag
puts("Congratulation!\n");
接下来写脚本,把text逆向回去
text = 'killshadow'
key ='adsfkndcls'
flag = ""
for i in range(0,len(text)):
for x in range(0,128): # 用碰撞的思想
if chr(x).isalpha(): # 判断x是否是字符串
temp = (x - 39 - ord(key[i]) + 97) % 26 + 97
# print(text[i]+" "+chr(temp)+" "+chr(x))
if text[i] == chr(temp):
flag = flag + chr(x)
break
print(flag)
luck_guy
放入工具中查壳,无壳
分析源代码。有两个未定义的函数,分别点进去看看
在patch_me函数发现一个get_flag函数
在case1中,f1 = GXY{do_not_ ,strcat函数把f1和s连接,又把f2和s连接,所以flag = f1+f2
case4中发现,s = \x7Ffo`guci(\x7在ascll中代表删除,对应ascll127)
由于小端序,s = icug`ofF\x7,strcat函数连接f2和s。
所以f2 = icug`ofF\x7,f2显然不符合flag的格式
*(&f2 + j)表示的是从f2中向后偏移j个位置的内存位置上的值
case5中有一个处理f2的函数,写脚本逆向处理得到另一半flag
f = [105, 99, 117, 103, 96, 111, 102, 127]
a = [0]*8
for j in range(8):
if j % 2 == 1:
a[j] = f[j] - 2
else:
a[j] = f[j] - 1
for j in range(len(a)):
print(chr(a[j]), end='')