xor
将程序拖进ida,找到flag相关字样,F5进去,直接可以看到主函数内容
其中代码大概意思为数组前后位异或后,与global
对应字符串比较前33位,即ord('!')
,如果相同则返回Success
,也就是得到了flag
双击global
可以找到其对应的一系列字符
将其提取出来按照主函数意思编写代码,还原flag
s = ['f',0xA,'k',0xC,'w&O.@',0x11,'x',0xD,'Z;U',0x11,'p',0x19,'F',0x1F,'v"M#D',0xE,'g',6,'h',0xF,'G2O',0]
for i in range(len(s)):
if(isinstance(s[i],int)):
s[i] = chr(s[i])
s = "".join(s)
flag = 'f'
for i in range(1,len(s)):
flag += chr(ord(s[i]) ^ ord(s[i-1]))
print(flag)
得到flag:flag{QianQiuWanDai_YiTongJiangHu}
reverse3
程序拖进ida,可以先看到Str2
,在之后会用到,再f5到主函数里
可以看到在Dest[]
数组经过一番操作后与Str2
比较,如果相同则为flag,而现在有了Str2
,所以我们需要找出Dest
,先对for循环进行逆操作
str2 = 'e3nifIH9b_C@n@dH'
dest = ''
for i in range(len(str2)):
dest += chr(ord(str2[i]) - i)
print dest
得到dest
后,再看上面的操作,先对v1
进行一番操作,再将v1
赋值给dest
,所以再看v1
的操作
看到这里多次出现的aAbcdefghijklmn
,点进去可以看到很熟悉的base64编码表
于是尝试对dest
进行base64解码,即可得到flag:flag{i_l0ve_you}
不一样的flag
程序拖进ida,可以看到一长串的01
*11110100001010000101111#
f5到主函数,可以看到里面有上下左右,推测是一个走迷宫游戏
01序列长度为25,从这可以看出是一个5*5的迷宫
*1111
01000
01010
00010
1111#
而且只要遇到1
就退出,遇到#
则返回
ok, the order you enter is the flag!
句意为:输入的顺序为flag
所以从*
出发走0
最后到#
,得到flag:flag{222441144222}
SimpleRev
file命令查看,发现是64位程序,拖进ida找到关键函数
unsigned __int64 Decry()
{
char v1; // [rsp+Fh] [rbp-51h]
int v2; // [rsp+10h] [rbp-50h]
int v3; // [rsp+14h] [rbp-4Ch]
int i; // [rsp+18h] [rbp-48h]
int v5; // [rsp+1Ch] [rbp-44h]
char src[8]; // [rsp+20h] [rbp-40h]
__int64 v7; // [rsp+28h] [rbp-38h]
int v8; // [rsp+30h] [rbp-30h]
__int64 v9; // [rsp+40h] [rbp-20h]
__int64 v10; // [rsp+48h] [rbp-18h]
int v11; // [rsp+50h] [rbp-10h]
unsigned __int64 v12; // [rsp+58h] [rbp-8h]
v12 = __readfsqword(0x28u);
*(_QWORD *)src = 357761762382LL; // 数据在内存中是小端存储,所以转换成字符串的时候要逆序,实际是'NDCLS'
v7 = 0LL;
v8 = 0;
v9 = 512969957736LL; // 此处也同理,得到'hadow'
v10 = 0LL;
v11 = 0;
text = join(key3, (const char *)&v9); // 进一步分析可知join()函数起到衔接两个字符串的作用,key3='kills',连接在一起就是'killshadow'
strcpy(key, key1); // key1='ADSFK'
strcat(key, src); // 连接两个字符串后,key='ADSFKNDCLS'
v2 = 0;
v3 = 0;
getchar();
v5 = strlen(key); // v5=10
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 ) // 将key的大写字母转换成小写,此时key='adsfkndcls'
key[i] = key[v3 % v5] + 32;
++v3;
}
printf("Please input your flag:", src);
while ( 1 ) // 通过这里开始的while循环得到最终的flag
{
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; // key='adsfkndcls'
}
else // ( v1 > 96 && v1 <= 122 ) 对小写字母进行操作
{
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) ) // 最后将str2与text进行比对,如果相同,输入的值即为flag,text='killshadow'
puts("Congratulation!\n");
else
puts("Try again!\n");
return __readfsqword(0x28u) ^ v12;
}
我们现在已知最后对比时的字符串为killshadow
,而且只对大小写字母进行操作,所以直接写脚本用所有大小写字母试一下即可
key = 'adsfkndcls'
text = 'killshadow'
dic = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
flag = ''
for i in range(10):
for x in dic:
if chr((ord(x) - 39 - ord(key[i]) + 97) % 26 + 97) == text[i]:
flag += x
print flag
可以发现最后输出flag的时候既有大写字母,也有小写字母,而且恰好是交替出现,说明其实有两种答案,但是本题flag只考虑了大写字母的情况,所以将其中的大写字母挑出来即可,flag:flag{KLDQCUDFZO}
刮开有奖
32位程序,用ida打开后,可以看到WinMain
主函数,点进去,找到关键函数
反编译成C,其中比较关键的代码在下图
题干提示输入即为flag,上图中也提到了flag有8位,其中赋值了v7~v17,然后通过sub_4010F0
函数对v7~v17进行了操作
int __cdecl sub_4010F0(int a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx
result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = 4 * i;
v6 = *(_DWORD *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(_DWORD *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(_DWORD *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(_DWORD *)(a1 + 4 * result) = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}
把这段函数改成可以执行的C代码,把v7~v17代入后执行
#include<stdio.h>
int __cdecl sub_4010F0(char *a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx
result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = i;
v6 = a1[i];
if ( a2 < result && i < result )
{
do
{
if ( v6 > a1[result] )
{
if ( i >= result )
break;
++i;
a1[v5] = a1[result];
if ( i >= result )
break;
while ( a1[i] <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = i;
a1[result] = a1[i];
}
--result;
}
while ( i < result );
}
LABEL_13:
a1[result] = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}
int main()
{
char a[20] = {90,74,83,69,67,97,78,72,51,110,103};
sub_4010F0(a, 0, 10);
for(int i = 0; i < 11 ; i++)
printf("%d ",a[i]);
return 0;
}
执行完可以发现v7~v17对应的数字发生了改变,变成了:51 67 69 72 74 78 83 90 97 103 110
再看最后得到flag的部分
if ( String == v7 + 34 // v7经过操作后变为51,51+34=85,即'U'
&& v19 == v11 // v11经过操作后变为74,即'J'
&& 4 * v20 - 141 == 3 * v9
&& v21 / 4 == 2 * (v14 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
其中v4和v5在之前被执行了sub_401000
函数,进函数看到byte_407830
这个类似数组一样的东西,点进去跳转到汇编中
可以看到熟悉的base64编码字符集,推测ak1w
和V1Ax
是两个经过base64编码的字符串,拼接在一起解码后恰好可以得到WP1jMp
(有个顺序上的前后关系,先是v23,后是v20,所以要颠倒一下),再加上开头的两位U
和J
恰好一共八位,即为flag:flag{UJWP1jMp}
Java逆向解密
将class文件拖入jd-gui即可完成反编译,得到源码
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Scanner;
public class Reverse
{
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
System.out.println("Please input the flag :");
String str = s.next();
System.out.println("Your input is :");
System.out.println(str);
char[] stringArr = str.toCharArray();
Encrypt(stringArr);
}
public static void Encrypt(char[] arr)
{
ArrayList<Integer> Resultlist = new ArrayList();
for (int i = 0; i < arr.length; i++)
{
int result = arr[i] + '@' ^ 0x20;
Resultlist.add(Integer.valueOf(result));
}
int[] KEY = { 180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65 };
ArrayList<Integer> KEYList = new ArrayList();
for (int j = 0; j < KEY.length; j++) {
KEYList.add(Integer.valueOf(KEY[j]));
}
System.out.println("Result:");
if (Resultlist.equals(KEYList)) {
System.out.println("Congratulations!");
} else {
System.err.println("Error!");
}
}
}
源码中给出了KEY数组,我们需要按照其加密方式来逆向解密,即KEY[i] -= '@' ^ 0x20
,python实现即可
key = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
flag = ''
for i in key:
flag += chr( i - ord('@') ^ 0x20 )
print flag
得到flag:flag{This_is_the_flag_!}
findit
需要逆向apk文件,直接拖进JEB进行反编译:行为 → 解析,得到关键源码
可以看到其中有类似flag的字样:pvkq{m164675262033l4m49lnp7p9mnk28k75}
,而qvkq与flag恰好差10,想到凯撒加密,直接得到flag
flag{c164675262033b4c49bdf7f9cda28a75}
info 评论功能已经关闭了呐!