基础逆向分析学习

本文整理 Android 注册逻辑、Java 解密、ELF 与 Windows 程序等基础逆向分析题目的思路和脚本。

基本函数

char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。

简单注册器

刚接触到安卓逆向,用jdx打开apk包发现注册逻辑

image-20260914162515710

编写exp:

1
2
3
4
5
6
7
8
9
10
11
x = list('dd2940c04462b4dd7c450528835cca15')
x[2] = chr(ord(x[2]) + ord(x[3]) - 50)
x[4] = chr(ord(x[2]) + ord(x[5]) - 48)
x[30] = chr(ord(x[31]) + ord(x[9]) - 48)
x[14] = chr(ord(x[27]) + ord(x[28]) - 97)
for i in range(0,16):
a = x[31 - i ]
x[31 - i] = x[i]
x[i] = a
print("flag{" + "".join(x) + "}")

获得flag为flag{59acc538825054c7de4b26440c0999dd}

JAVA逆向解密

image-20260914164100559

看 Encrypt()的逻辑,flag作为参数传入

1
2
3
4
for (char c : arr) {
int result = (c + '@') ^ 32;
Resultlist.add(Integer.valueOf(result));
}

这是加密的主要逻辑

逆向一下加密逻辑就是

c = result ^ 32 - ord(‘@’)

后面使用KEY来做对比

所以编写脚本

1
2
3
4
5
6
7
8
KEY = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
result = ""
for value in KEY:
value = value ^ 32
value = value - 64
cha = chr(value)
result = result + cha
print("flag{"+result+"}")

flag{This_is_the_flag_!}

luck_guy

解压之后先查壳,发现无壳,是ELF64位文件

image-20260914181208518

将luck_guy拖进IDA中分析

image-20260914175814994

发现是switch-case函数,逐个分析一下每一个case

case1的作用是先将s设置为空,将f1和f2都链接在s之后,那么s可能就是要找的flag,点击了一下f1,发现了f1的值

image-20260914182309626

case2和case3 都是输出,先不管

case4这里给了 s = ‘\x7Ffoguci' ,刚开始查文件时候说了是ELF64文件,所以它存储的时候是小端存储,但是在IDA的显示中会变为大端存储,所以需要把s逆置一下,也就是s = icugof,然后会把s插入f2之后

Case5是对f2进行处理,这个循环的含义是如果j为奇数,就把f2 - 2,如果是偶数,就把f2 - 1

所以可以猜想一下,case4 -> case5 -> case1 就可以得到flag

编写脚本走一圈

1
2
3
4
5
6
7
8
9
10
f1 =list('GXY{do_not_')
f2 =list('icug`of')

for i in range(0,7):
if i % 2 == 0:
f2[i] = chr(ord(f2[i]) - 1)
else:
f2[i] = chr(ord(f2[i]) - 2)

print("".join(f1)+"".join(f2)+"}")

得到flag

GXY{do_not_hate_me}

刮开有奖

先查壳,没什么有效信息

image-20260914194136984

直接丢IDA,看到DIalogFunc直接跟进去

image-20260914195352575

这里大概就能看到加密的主体了,将这些东西都修复了就变成这样了

image-20260914195534738

第一点,输入字符的长度必须是8

第二点,下面的这些变量肯定是和flag有关

跟进sub_4010f0函数

image-20260914195655942

发现函数是升序的快速排序,给函数更一下名

那么意思就是将上面的变量进行升序排序

1
2
3
4
5
key = list("ZJSECaNH3ng")
key.sort()
print("".join(key))

# 3CEHJNSZagn

再往下看sub_401000函数,跟进去

image-20260914195833966

观察函数逻辑,发现是base64加密,跟进去byte_407830中,看一下base64表是没有变的image-20260914195931446

在主函数的逻辑中,v4 v5都是被base64加密之后的变量

最后看if的判断条件

image-20260914200246043

排序后的元素为3CEHJNSZagn

1️⃣v7[0]表示的是第一个元素 也就是3 ,string[0] = v7[0] + 34

2️⃣v10代表的是第五个元素 对应的也就是J

3️⃣逆运算一下 string[2] = (3 * v8 + 141) / 4,这里的v8是第三个元素,也就是E

4️⃣逆运算一下 string[3] = 2 * (v13 / 9) * 4,这里的v13是第八个元素 ,也就是Z

5️⃣6️⃣都是做比较,将ak1w和V1Ax base64解密一下再做比较,因为上面说过了 v4 v5都是base64加密之后的变量,解密之后为ak1w -> jMp V1Ax -> WP1

从上往下求一下

1
2
3
4
5
6
7
8
key = "3CEHJNSZagn"

string0 = chr(ord(key[0]) + 34)
string1 = key[4]
string2 = chr(int((3 * ord(key[2]) + 141) / 4))
string3 = chr(int(ord(key[7]) / 9 * 2 * 4))

print(string0 + string1 + string2 + string3)

得到UJWP,因为已知长度是8,上面两个字符串base64解密后为jMp和 WP1,做一下比较可以得到WP1在前面

所以flag为flag{UJWP1jMp}

[BJDCTF2020]JustRE

进去之后查看字符串,发现一个和flag很像的东西,跟进去

image-20260914204135246

image-20260914204110161

发现点击次数为19999输出flag,再往下看format,把19999和0带入进去得到flag

flag{1999902069a45792d233ac}

rome

1
2
3
4
5
6
7
8
9
10
11
12
13
14
miwen = ['p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}']
mingwen = [''] * 38

for i in range(0,38):
if (miwen[i] >= 'A' and miwen[i] <= 'Z') or (miwen[i] >= 'a' and miwen[i] <= 'z'):
y = ord(miwen[i]) + 16
if (y > ord('Z') and y < ord('a')) or (y >= ord('z')):
y -= 26
mingwen[i] = chr(y)
else:
mingwen[i] = miwen[i]

print("".join(mingwen))
print(mingwen)

[GWCTF 2019]pyre

拿到题目反编译后得到这样的python代码

image-20261012190202174

分析第二个循环一下能够知道,反着算就行,code的最后一位是不变的

由于最后一位code[i + 1]没变,从后往前走,code[i + 1] ^ code [i]得到的就是异或前的code[i]

从后往前异或完得到的就是num

然后分析第一个循环

num = (input[i] + i) % 128

反着算就是flag

num = (input[i] - i) % 128

编写exp

1
2
3
4
5
6
7
8
9
code = ['\x1f','\x12','\x1d','(','0','4','\x01','\x06','\x14','4',',','\x1b','U','?','o','6','*',':','\x01','D',';','%','\x13']
len = len(code)
flag = ''

for i in range(len - 2, -1, -1):
code[i] = chr(ord(code[i]) ^ ord(code[i + 1]))
for i in range(len):
flag += chr((ord(code[i]) - i )% 128)
print(flag)