寒假刷题记录reverse2
攻防世界
Reverse
1.Hello,CTF
拖入exe
无壳,拖入32位IDA
发现输入字符串大于17,程序结束0x11 = 17
小于17,则v10与v13比较,相同则输出:aSuccess
而v13一定大于17 ,v13=437261636b4d654a757374466f7246756e
进制转换,发现每位都在1-9 a-f之内,猜测为16位,转换如图
而题目描述为菜鸡发现Flag似乎并不一定是明文比较的
得到flag为CrackMeJustForFun
2.re1
拖入exe无壳,拖入32位IDA,找到main函数F5反汇编
看到有个strcmp函数,比较v5和v9,然后判断v3,根据v3给出相应的结果
双击跟进aFlagGet,证明思路正确
跟进xmmword_413E34
xmmword的值已经出来了:那么v5的值就是3074656D30633165577B465443545544h了
v5应该是16进制表示的,看下strcmp函数,有个将v5转换为字符串的函数
找到在线16进制转换字符串
通过文字倒序得到DUCTF{We1c0met0
发现flag并不完整,想到题干
故猜测flag为DUCTF{We1c0met0DUCTF}
3.logmein
拖入exe,无壳,拖入64位IDA,找到main函数,F5反汇编
__isoc99_scanf(“%32s”, s);
这一行代码就是我们输入的flag
将我们输入的flag的每一位与v7[i%v6]^v8[i]比较,如果有任意一位不相等,则输出“Incorrect password!”
把v7转换成字符型,IDA上直接显示的是
v7 = ‘ebmarah’;
需要注意的是,x86系列的CPU都是以小端序储存数据的,即低位字节存入低地址,高位字节存入高地址,所以正确的字符串应该反过来,即
v7=’harambe’;
脚本:
v7 = 'harambe'
v8 = ':\"AL_RT^L*.?+6/46'
flag = ''
for i in range(len(v8)):
c = ord(v7[i % 7]) ^ ord(v8[i])
flag += chr(c)
print(flag)
得到flag为RC3-2016-XORISGUD
4.Getit
拖入exe,无壳,拖入64位IDA
双击跟进p[j]
可以看到p[i]数组存放的是无序的整数,也就是说每次在/tmp/flag.txt文件中写入的flag是不按顺序写的,且每次只出现一个字符,需要自己排序。
双击跟进t
发现harifCTF{????????????????????????????????}
53h转换成字符串为‘S’
脚本:
key1="c61b68366edeb7bdce3c6820314b7498"
v5=0
flag=""
while v5 < len(key1):
if v5 & 1:
v3=1
else:
v3=-1
flag+=chr(ord(key1[v5])+v3)
v5+=1
print(flag)
运行得到b70c59275fcfa8aebf2d5911223c6589
所以flag为SharifCTF{b70c59275fcfa8aebf2d5911223c6589}
看到的其他解法:
法二:GDB动态调试
首先我们知道了下面strlen(&t)的t是flag程序运行后生成的flag,那我们把鼠标放在那一行上看一下下面的反汇编行数,如下所示是400824,那么我们在反汇编窗口跟上。
可以看到反汇编中400824行的确是_strlen函数,而它上面就是把&t移入了edi,所以在GDB中我们断点400824,然后查看edi寄存器即可。
所需命令:
b *0x400824
r
这里用的是hyperpwn插件:
可以看到flag就在RDI寄存器里
法三:C语言脚本
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#pragma warning(disable:4996)
int main(void)
{
char v3;
__int64 v5;
char s[] = "c61b68366edeb7bdce3c6820314b7498";
char t[] = "SharifCTF{????????????????????????????????}";
v5 = 0;
while (v5 < strlen(s)) {
if (v5 & 1)
v3 = 1;
else
v3 = -1;
*(t + v5 + 10) = s[v5] + v3;
v5++;
}
printf("%s", t);
system("PAUSE");
return 0;
}
法四:在IDA动态截停
5.no-strings-attached
拖入exe,无壳,拖入32位IDA
找到main函数,F5反汇编
双击跟进authenticate()函数,分析如下
void authenticate()
{
wchar_t ws[8192]; // [esp+1Ch] [ebp-800Ch]
wchar_t *s2; // [esp+801Ch] [ebp-Ch]
s2 = (wchar_t *)decrypt(&s, &dword_8048A90); //decrypt表示加密
if ( fgetws(ws, 0x2000, stdin) ) //进行输入
{
ws[wcslen(ws) - 1] = 0;
if ( !wcscmp(ws, s2) ) //判断输入的ws是否等于加密过后的s2
wprintf((int)&unk_8048B44); //如果ws=s2,得到unk_8048B44,跟进得到success!
else
wprintf((int)&unk_8048BA4);
}
free(s2);
}
当 ws 和 s2 相等时,会输出正确结果,那么s2就是flag,而s2经过了decrypt()加密。
那么跟进decrypt()函数:
它先把参数 s 复制给 dest,与就是s=dest,然后把 dest 的每个值减去 a2 的值,然后再返回加密后的 dest。那么,我们就把s与a2找出来,相减就得到flag。
双击跟进s
选中按shift+e提取出来
根据得到的信息写c脚本:
#include <stdio.h>
int main()
{
int x=0,i=0,j=0;
int s[] =
{
58, 20, 0, 0, 54, 20, 0, 0, 55, 20,
0, 0, 59, 20, 0, 0, 128, 20, 0, 0,
122, 20, 0, 0, 113, 20, 0, 0, 120, 20,
0, 0, 99, 20, 0, 0, 102, 20, 0, 0,
115, 20, 0, 0, 103, 20, 0, 0, 98, 20,
0, 0, 101, 20, 0, 0, 115, 20, 0, 0,
96, 20, 0, 0, 107, 20, 0, 0, 113, 20,
0, 0, 120, 20, 0, 0, 106, 20, 0, 0,
115, 20, 0, 0, 112, 20, 0, 0, 100, 20,
0, 0, 120, 20, 0, 0, 110, 20, 0, 0,
112, 20, 0, 0, 112, 20, 0, 0, 100, 20,
0, 0, 112, 20, 0, 0, 100, 20, 0, 0,
110, 20, 0, 0, 123, 20, 0, 0, 118, 20,
0, 0, 120, 20, 0, 0, 106, 20, 0, 0,
115, 20, 0, 0, 123, 20, 0, 0, 128, 20,
0, 0,
};
int b[] =
{
1, 20, 0, 0, 2, 20, 0, 0, 3, 20,
0, 0, 4, 20, 0, 0, 5, 20, 0, 0,
};
while(i < 152)
{
x = s[i ++] - b[j ++ % 20];
if(x>32)
printf("%c",x);
}
return 0;
}
得到flag为9447{you_are_an_international_mystery}
python脚本为:
s = [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]
a = [5121, 5122, 5123, 5124, 5125]
v6 = len(s)
v7 = len(a )
v2 = len(s)
v4=0
while v4<v6:
for i in range(0,5):
if(i<v7 and v4<v6):
s[v4]-=a[i]
v4 += 1
else:
break
for i in range (38):
print(chr(s[i]),end="")