不对的地方还请大佬多多指出–
首先用exeinfope查看为64位 用IDA打开 f5得到源码
printf("Input your flag:\n", 0LL);
get_line(v6, 256LL);
if ( strlen(v6) != 33 )//这里也就是flag的长度了
goto LABEL_12;
for ( i = 1; i < 33; ++i )
v6[i] ^= v6[i - 1];
v3 = global;
if ( !strncmp(v6, global, 0x21uLL) )//这里是关键点与比较上述运算后的global比较,一致则成功
printf("Success", v3);
else
LABEL_12:
printf("Failed", v3);
result = __stack_chk_guard;
if ( __stack_chk_guard == v7 )
result = 0;
return result;
追踪global(点击它)后可以得到一串字符,那么这里逆推回去得到原v6
也就是flag
选个字母右键选择16进制然后复制出来这样容易写代码
这里涉及一个知识点:两次异或操作得到的是本身
源码这里是:v6[i] ^= v6[i - 1];我们复原的话只需要前面那个和后面那个字符异或就行 举个例子: 以变量来说(0 1 1’相当于是变量这里举个例子说明) 其中1’和2’等等是题目得到的变量
0^1=>1' 1'^2=>2' 2'^3=>3' 我们再求 1 2 3 的时候只需要
1= 1'^0 2= 2'^1'
所以我们的脚本如下
glo=[0x66,0x0a,0x6b,0x0c,0x77,0x26,0x4F,0x2E,0x40,0x11,0x78,0x0D,0x5A,0x3B,0x55,1,0x70,0x19,0x46,0x1F,0x76,0x22,0x4D,0x23,0x44,0x0E,0x67,0x6,0x68,0x0f,0x47,0x32,0x4f]
s=''
for i in range(1,len(glo)):
a=glo[i]^glo[i-1]
s+=chr(a)
print(s)
得到flag =>flag{QianQiuWanTqi_YiTongJiangHu}
老套路 还是用exeinfope得出 无壳 32位 用IDA打开
F5直接进入主函数
sub_41132F("please enter the flag:");
sub_411375("%20s", &Str);
v0 = j_strlen(&Str);
v1 = (const char *)sub_4110BE(&Str, v0, &v11);
strncpy(Dest, v1, 0x28u);
v8 = j_strlen(Dest);
for ( j = 0; j < v8; ++j )
Dest[j] += j;
v2 = j_strlen(Dest);
if ( !strncmp(Dest, Str2, v2) )
sub_41132F("rigth flag!\n");
else
sub_41132F("wrong flag!\n");
s=''
str1= 'e3nifIH9b_C@n@dH'
for i in range(len(str1)):
s+=chr(ord(str1[i])-i)
print(s)
得到e2lfbDB2ZV95b3V9
然后以为是flag 一直不对 参考了大佬的博客 原来是还有个base64
sub_4110BE(&Str, v0, &v11);点进去 一大串看不懂的代码 还是太菜了继续加油!
走迷宫题 进入main 追随start 得到 10字符串
*11110100001010000101111#
分成5行
*1111
01000
01010
00010
1111#
1就退出 # 就成功 走的数就是flag 得到flag
老办法exeinfope一波
用64位 IDA打开进入主函数 得到代码
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char v4; // [rsp+Fh] [rbp-1h]
while ( 1 )
{
while ( 1 )
{
printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv, envp);
v4 = getchar();
if ( v4 != 100 && v4 != 68 )
break;
Decry();
}
if ( v4 == 113 || v4 == 81 )
Exit();
puts("Input fault format!");
v3 = getchar();
putchar(v3);
}
}
老套如用IDA64位打开跟进main 函数进入Decry()函数
代码如下
v7 = 0LL;
v8 = 0;
v9 = 512969957736LL;
v10 = 0LL;
v11 = 0;
text = (char *)join(key3, &v9);
strcpy(key, key1);
strcat(key, src);
v2 = 0;
v3 = 0;
getchar();
v5 = strlen(key);
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
key[i] = key[v3 % v5] + 32;
++v3;
}
printf("Please input your flag:", src);
while ( 1 )
{
v1 = getchar();
if ( v1 == 10 )
break;
if ( v1 == 32 )
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 122 )
{
if ( v1 > 64 && v1 <= 90 )
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}
else
{
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) )
puts("Congratulation!\n");
else
puts("Try again!\n");
return __readfsqword(0x28u) ^ v12;
}
v9 = 512969957736LL;
text = (char *)join(key3, &v9);
strcat(key, src);
很容易找到key src
需要注意的是,x86系列的CPU都是以小端序储存数据的,即低位字节存入低地址,高位字节存入高地址,所以正确的字符串应该反过来即
v9 = ‘hadow’;
将其反过来连接得到 text= killshadow
2. *src = NDCLS
3. 连接起来得到 :key= ‘ADSFKNDCLS’
用脚本得到新的key
key= 'ADSFKSLCDN'
v3=0
v5=len(key)
for i in range(v5):
if (ord(key[v3%v5])> 64 and ord(key[v3%v5])<=90):
print(chr(ord(key[v3 % v5])+32),end='')
v3+=1
key= adsfkndcls
以下就是主函数分析 :
如果满足再大小写之中并且满足
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
我们可以通过遍历的方法得到想要的字符串
代码如下
import string
dict=string.ascii_letters
key='adsfkndcls'
text='killshadow'
v5=len(text)
for i in range(len(text)):
for j in dict:
if((ord(text[i]) == (ord(j)-39-ord(key[i%v5])+97)%26+97)):
print(j)
这里发现不对 不知道为什么是只有大写,没有过滤了小写 。。希望能得到大师傅的解答
得到flag
如果有错误的话请多多指正