新手练习区
Hello, CTF
下载附件,查壳,32位,无壳
运行一下程序,查看效果,可以看到要我们输入,等会可以根据这串字符串判断flag的位置
拖进ida32位,静态分析,shift+f12
查看字符串,发现 success!
下面还有一个可疑字符串怀疑是进行处理过的flag
双击查看字符串存储的位置,ctrl+x
交叉引用,查看在那个地方使用了这个字符串
进入后追踪到这个位置,f5
查看c代码,会汇编的也可以直接干汇编
可以看到用户只能输入最多17个字符,超过便会结束,也就是falg不会超过17,但是v10和v13进行比较,v13有34个字符,这是因为do while循环里,sprintf()把v4以asc_408044输出到v8,再把v8追加到v10后面,我们可以查看asc_408044
,这里储存的%x,也就是以十六进制输出,所以逆推就是输入的字符串以十六进制输出等于v13这个字符串,所以flag就是v13这串数据以十六进制转换为字符串。
insanity
下载附件不是可执行文件,文件分析,32位文件。
查找字符串看看有没有有用信息,shift+f12
,flag直接就出来了
python-trade
下载附件是一个pyc文件,需要进行反编译,这里我们用在线python反编译的网站。
这里是python脚本,根据输入进行^处理后+16,写出对应的python脚本
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)
re1
下载附件,运行查看效果,查壳,32位
直接进主函数main,反编译,这里直接就是进行了比较判断,我们可以看到黄色部分的地方,双击进去看到一串数据,选中这串数据r
一下就得到逆序的flag
game
运行是一个游戏,查壳,无壳32位
进入主函数,看到下面,猜测flag在这里,因为是一个游戏,所以游戏成功应该会弹出flag,我们直接找flag位置,这里一个判断,都为1进入下面这个函数,我们进函数看看。
分析一下,flag在这没错了,下面循环一次性用两个值,分别是从v59和v2地址开始,这里数值和循环用到的数值是一样的,基本确定flag从这里出。
写脚本
#include <stdio.h>
int main ()
{
int a[60]={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[60]={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};
for(int i = 0;i < 56;i++)
{
b[i] ^= a[i];
b[i] ^= 0x13u;
printf("%c",b[i]);
}
return 0;
}
open-source
直接分析代码,看出条件,把值套进去,得出flag
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 4) { //argc为4
printf("what?\n");
exit(1);
}
unsigned int first = atoi(argv[1]);
if (first != 0xcafe) { //first=0xcafe
printf("you are wrong, sorry.\n");
exit(2);
}
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) { //second % 17 == 8
printf("ha, you won't get it!\n");
exit(3);
}
if (strcmp("h4cky0u", argv[3])) { //长度为7
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;
}
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
unsigned int hash = 0xcafe * 31337 + 8 * 11 + 7 - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}
simple-unpack
查壳,upx壳,拖进kali执行,upx -d 文件名 进行脱壳,脱完后拖出来,放64位分析,直接出flag
logmein
无壳64位
简单的算法,写对应脚本
v8 = ":\"AL_RT^L*.?+6/46"
v7 = "harambe"
v6 = 7
flag = ""
for i in range(0,len(v8)):
flag += chr(ord(v7[i % v6]) ^ ord(v8[i]))
print(flag)
no-strings-attached
无壳32位
可以看到后面对ws和s2进行比较,s2后面这函数进行一系列操作,预判flag位置。
我们看汇编代码,可以看到这里进入decrypt函数后把flag存在eax里,我们可以用gdb调试,来查看flag
这里我们下断点下在调用decrypt这个函数里 *0x8048720,然后r运行,n 单步执行,最后查看我们eax的值(一般临时值存放在eax)x /sw $eax
x是查看地址,s是字符串显示,w是四个字节
我们也可以提取数据写脚本,注意我们提取数据后把后面四个0给删除,学c应该知道,字符串后面会默认加’/0’,所以我们要删除四个0.
#include <stdio.h>
int main ()
{
unsigned char 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},
c[]={1,20,0,0,2,20,0,0,3,20,0,0,4,20,0,0,5,20,0,0};
int v4 = 0,
v7 = sizeof(c) / sizeof(unsigned char),
v6 = sizeof(s) / sizeof(unsigned char);
while(v4 < v6)
{
for(int i = 0;i < v7 && v4 < v6;++i)
printf("%c",s[v4++]-c[i]);
}
return 0;
}