reverse 1
在下载后得到相应的程序,拖入到DIE中,检测到程序是没有加壳的
然后拖入IDA x64中,在View-A界面,查看有没有字符串,简单的提供一些信息
查看字符串 1、直接看 2、shift+F12
定位到一句 'this is the right flag'
然后ctrl+x(交叉引用)查看是哪段函数调用了该字符串,点击OK,查看其汇编代码。
然后F5查看伪c代码
首先定位到比较语句,发现如果str1 == str2,则正确
strncmp(str1,str2,v3)是把str1与str2两字符串的前v3位数做一个比较,若str1=str2,返回0;大于返回正数,小于返回负数
sub_1400111D1是print函数,相应的sub_14001128F是scanf函数
锁定Str2 = {hello_world}
将程序向上分析,发现了一段比较替换的,赋值为ASCII 111,选中字符按R后,将数字转为字符,发现是将o替换成0
所以flag{hell0_w0rld}
reverse2
下载文件后,发现文件并不是exe文件,但是拖入DIE中确发现是一个64位的文件
然后拖入IDA后,发现this is right flag字样
F5进入伪码后,发现和上一题类似,就是替换比较
然后寻找文中的flag
发现flag{hacking_for_fun},将r和i替换成1后,就是最终的flag
新年快乐
首先下载下来附件后,检测后发现是PE32位程序,然后根据wp显示有UPX加壳
脱壳后,拖入IDA,然后锁定true flag,查看伪码后,发现了语句
审计代码后,发现了flag
XOR
根据题目XOR,发现题目应该与异或有关
拖入DIE后,发现是mac文件,然后才有IDAx64打开后
首先发现INPUT YOUR FLAG
然后F5编译出伪代码后,进行代码审计
发现首先flag长度应该为33位
然后将第i位和i-1位进行异或,然后与glabal进行比较
其中shift+e调出数组中的字符,调整为c无符号数组(十进制)
编写脚本,再次进行异或,就可以得到flag,两次异或后还原,一致后输出
注意glabal参数,定位后,向上找,先确定参数类型,然后从界面的左侧可以看出来,然后再次确定参数
flag{QianQiuWanDai_YiTongJiangHu}
helloword
下载下来文件后,发现是apk结尾,是Android文件,然后拖入AndrodiIDE
在smali-com-example-helloword中第二个文件中发现了flag
reverse_3
打开文件后,发现是PE32,加载后,发现input flag
查找到最后,存在比较,一致后为flag
str2 e3nifIH9b_C@n@dH
先将其for循环解除,e2lfbDB2ZV95b3V9
观察这个,发现也不像是flag,然后发现上面还有一个函数,点进去后,有一个数组,限定是64,点进去发现是大小写英文字母以及+/=,猜测应该是某种编码
不一样的flag
下载下来附件后,检测到是PE32的文件,然后通过IDA编译后,发现一串字符,感觉flag应该和这个有关系
然后向下阅读伪代码,发现输入1、2、3、4后,赋值,判断,然后v3和v4加减
落到最后,发现如果是1,则退出,如果是#则最后输出
根据wp中发现。属于迷宫题
*1111
01000
01010
00010
1111#
从*出发,到# 需要输入22244114422
那么flag就是刚刚的数字
https://blog.csdn.net/qq_66455531/article/details/129645357
simpleRev
下载后得到一个elf文件,DIE后发现是一个64位的,放入IDAx64中
编译成伪代码后,第一遍没有看到flag,函数也很简单
第二遍再看的时候,发现Decry()
点进去看,发现最后的Congratulation!
沿着代码,向上看,有比较,猜测和text比较的str2应该就是flag
然后分别找到
key = killshadow
key = ADSFK
src = SLCDN
key = ADSFKNDCLS
这里有一个知识点,就是计算机中更倾向于小端排序,即将多位数的低位放在较小的地址处,,高位放在较大的地址处。与人的阅读习惯相反,那么SLCND 按照人们的阅读习惯就是DNCLS
然后接下来就是将字符串,从大写转为小写
key = adsfkndcls
根据伪代码的语句,前两句判断,根据text字符串,我认为是不需要进行逆向的,然后在往下,分别看到了
if ( v1 <= '`' || v1 > 'z' )
{
if ( v1 > '@' && v1 <= 'Z' )
结合ASCII码表判断,就是要求输入字符是大写字母或者小写字母
在经过
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
进行转换
因为代码能力的问题,只能选择爆破
猜测应该是输入大写的字符,然后转,先用大写的字母爆破是因为+97,如果0+97,正好是a
最后,脚本
text = 'killshadow'
key = 'adsfkndcls'
burte = 'QWERTYUIOPASDFGHJKLZXCVBNM'
v3 = 0
v5 = len(key)
flag = ''
for j in text:
for i in range(len(burte)):
v1 = (ord(burte[i]) - 39 - ord(key[v3 % v5]) + 97) % 26 +97
if ord(j) == v1:
flag += burte[i]
v3 += 1
输出KLDQCUDFZO后,加上flag{},flag正确
print(flag)
Java逆向解密
采用jd-gui打开后,发现了代码
和PE文件一样,最后都是比较,然后一致后输出
通过代码,发现有几句整型转换的语句,没有作用,扔掉
int[] KEY = {
180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
133, 191, 134, 140, 129, 135, 191, 65 };
KEY就是最后比较的
核心加密就是这一条
for (int i = 0; i < arr.length; i++) {
int result = arr[i] + 64 ^ 0x20;
}
逆向代码
keyList = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
133, 191, 134, 140, 129, 135, 191, 65 ]
flag = ''
for i in keyList:
result = (i - 64) ^ 32
flag += chr(result)
print(flag)
luck_guy
首先现在,解析后是64位程序,然后采用IDA 64打开
从字符串进入,不断确定函数,然后锁定到
strcat((char *)&s, f1); // f1 = GXY{do_not_
strcat((char *)&s, &f2);
但是f2没有办法确定,
但在接下来的case中发现了
s = 0x7F666F6067756369LL;
v5 = 0;
strcat(&f2, (const char *)&s);
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
*(&f2 + j) -= 2;
else
--*(&f2 + j);
}
&f2 + j就是用循环次数来控制地址的移动,但是也只是在本次循环时移动到这,并没有改变初始地址。
然后根据上面s = .....中的十六进制也就是它的地址
将地址以两位为一组,区分开,然后生成新的列表,根据上面的内容编写脚本
获得GXY{do_not_hate_me}
#reverse-luck_guy
flag = 'GXY{do_not_'
#因为计算机中多是小端序,所以
str = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
for i in range(len(str)):
if (i % 2 == 1):
#这个位置转不转为10进制的都是可以的,减去时候,要不以十进制转换为字符,要不以十六进制转换为字符
cha = chr(str[i] - 2)
else:
cha = chr(str[i] - 1)
flag += cha
print(flag)
[BJDCTF2020]JustRE
首先die分析为32位程序,然后点进去后发现没有找到与flag相关的信息
这时shift+F12,找出程序中的字符串,找到了
.data:00407030 0000001B C BJD{%d%d2069a45792d233ac}
.data:0040704C 00000010 C 您已经点了 %d 次
这个应该与flag有关
点进去后ctrl+x,交叉追踪后,F5编译伪代码,然后发现相关代码。
if ( dword_4099F0 == 19999 )
{
sprintf(String, " BJD{%d%d2069a45792d233ac}", 19999, 0);
SetWindowTextA(hWnd, String);
return 0;
}
这出代码应该是点击19999次后,弹出,%d%d应该就是19999和0
刮开有奖
首先根据题目,没有找到相关的内容,然后shift+F12,寻找所有的字符串,发现了一个字符串有些像,ctrl+x寻找交叉的内容,然后F5。进行编译,在伪代码中,发现string是一个被比对字符串
最后应该是求出该字符串
// string长度应该是8
{
v7[0] = 'Z'; // v7 = 90 = Z
v7[1] = 'J'; // v71 = 74 = J
v8 = 'S'; // v8 = 83 = S
v9 = 'E'; // v9 = 69 = E
v10 = 'C'; // v10 = 67 = C
v11 = 'a'; // v11 = 97 = a
v12 = 'N'; // v12 = 78 = N
v13 = 'H'; // v3 = 72 = H
v14 = '3'; // v14 = 51 = 3
v15 = 'n'; // v15 = 110 = n
v16 = 'g'; // v16 = 103 = g
sub_4010F0(v7, 0, 10); // 3CEHJNSZagn
sub_4010F0转为C代码,运行后,得到3CEHJNSZagn
根据这串代码,可以知道string0-7是哪个字符,v7就已经是3CEHJNSZagn
程序中的有的是地址相加。
if ( String[0] == v7[0] + 34 // string0 U
&& String[1] == v10 // v10 =J string1
&& 4 * String[2] - 141 == 3 * v8 // string2 = W
&& String[3] / 4 == 2 * (v13 / 9) // string 3 =P
&& !strcmp(v4, "ak1w") // V4 = jMp == V18 012
&& !strcmp( // V5 WP1 V18 012
v5,
"V1Ax") )
v4、v5是base64的加密程序,根据上面的比较语句,应该是加密后与其相同则原字符应该是解密的
v4 = sub_401000(v18, strlen(v18));
v5 = sub_401000(v18, strlen(v18));
最后解出 STRING = UJWP1jMp
简单注册器
下载下来附件后,得到一个apk结尾的文件,属于安卓的,然后拖入jdax中在mainactivity中发现了flag
然后根据判断的语句,以及最后的return
if (flag == 1) {
char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
x[2] = (char) ((x[2] + x[3]) - 50);
x[4] = (char) ((x[2] + x[5]) - 48);
x[30] = (char) ((x[31] + x[9]) - 48);
x[14] = (char) ((x[27] + x[28]) - 97);
for (int i = 0; i < 16; i++) {
char a = x[31 - i];
x[31 - i] = x[i];
x[i] = a;
}
String bbb = String.valueOf(x);
textview.setText("flag{" + bbb + "}");
return;
改写为python,输出得到flag
flag{59acc538825054c7de4b26440c0999dd}
pyre
下载下来的文件,是pyc,需要反编译
借助网站或者
pip install uncompyle6
uncompyle6 -o attachment.py attachment.pyc
反编译后
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7
print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
num = ((input1[i] + i) % 128 + 128) % 128进行操作
code += num
for i in range(l - 1):
code[i] = code[i] ^ code[i + 1]
print code
code = [
'%1f',
'%12',
'%1d',
'(',
'0',
'4',
'%01',
'%06',
'%14',
'4',
',',
'%1b',
'U',
'?',
'o',
'6',
'*',
':',
'%01',
'D',
';',
'%',
'%13']
则应该先对其进行异或预算,然后对num = ((input1[i] + i) % 128 + 128) % 128进行操作
((input1[i] + i) % 128 + 128) % 128
数学逻辑分析:
令(input1[i] + i)为X,
假设X > 128,对128取模后,得余数,余数在加128,在对128取余,还是得余数
假设X < 128,对128取模后得起本身, 那么余数在加128,对128取余,还是其本身
现在已知code列表,也就是各个num的值,也就是(input1[i] + i) % 128的结果。同时我也知道每个num所对应的i,一个未知数一个方程,input1[i]首先可以确定是可求的。
根据我上面假定数值的运算过程,很容易发现我想求input1[i]+5,只需要求n*128+3即可。那么n是多少呢?首先我的input1范围是0-127,i的范围是0-22,那么input1[i]+i显然小于150,也就是不可能超过128*2,那么n最大只能是1才能保证n*128+num小于150 。
所以input1[i]=128+num-i。但是这里又出现一个问题,也就是说,如果我的128+num-i大于128怎么办呢?我的flag是0-127的数值呀。所以我需要对它再进行一次取模:
则逆向代码为
ord(code[i])-i)%128
又或者
(a+b)%c=(a%c+b%c)%c、A=(B-C)%D,那么B=(A+C)%D,直接推出逆向代码
[ACTF新生赛2020]easyre
在IDA中查看后,发现逻辑很清晰,只有对V5进行了调取,然后与V4进行比较,那么V5就是我们要找到的flag,并且代码的最开始的比较字符内容,正好是ACT{},那么V5中的内容应该是{}中的内容,将V4中的字符转换为十进制的ASCII,然后在data_str中寻找索引位置,data_str要找全,然后确定下来索引位置+1,就是V5中字符的ASCII,代码如下:
data_start = ('~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJ'
'IHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"')
encrypt = [42,70,39,34,78,44,34,40,73,63,43,64]
flag = ''
for i in encrypt:
flag += chr(data_start.find(chr(i))+1)
'''
逆向想法
v4[i] = data_start(*((char *)v5+i)-1)
明确索引
v4[i]-转为了字符串中的ASCII,然后明确char * v5加的i就代表着flag的第几位
*()会获取相应的ASCII值 -1后,为索引
那么v4[i]的字符确定在data_str中相应字符的索引
索引就是*((char *)v5+i)-1的结果,然后加+1取字符就是flag的某位字符的ASCII
在转为字符就是flag
'''
print(flag)