# BUUCTF-Reverse —— 第一页的题目集合

1 篇文章 1 订阅

## reserve1

ctrl+x（交叉引用）查看是哪段函数调用了该字符串

## reserve2

.data:0000000000601080 flag            db 7Bh                  ; DATA XREF: main+34↑r
.data:0000000000601080                                         ; main+44↑r ...
.data:0000000000601081 aHackingForFun  db 'hacking_for_fun}',0


定义flag变量所存储的字符串为'{'，也就是数字7Bh，



db可以连续定义多个字符串，而数字0所代表的就是字符串的结束符’\0’。

## reserve3

IDA打开，F5反编译出伪代码。

（其实就是base64编码）

byte_41A144[0] >> 2

((byte_41A144[1] & 0xF0) >> 4) | (16 * (byte_41A144[0] & 3))

((byte_41A144[2] & 0xC0) >> 6) | (4 * (byte_41A144[1] & 0xF))

byte_41A144[2] & 0x3F


destination = 'e3nifIH9b_C@n@dH'
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
v12 = ''
for i in range(len(destination)):
v12 += chr(ord(destination[i])-i)
print(len(v12))
print(v12)
# v13是flag
v13 = ''
for i in range(0, len(v12), 4):
byte = [0, 0, 0, 0]
for j in range(4):
byte[j] = v12[i+j]
pos = [0, 0, 0, 0]
for j in range(4):
pos[j] = bin(table.index(byte[j]))[2:].zfill(8)
dec_byte0 = pos[0][2:] + pos[1][2:4]
dec_byte1 = pos[1][4:] + pos[2][2:6]
dec_byte2 = pos[2][6:] + pos[3][2:]
print(dec_byte0, chr(int(dec_byte0, 2)))
print(dec_byte1, chr(int(dec_byte1, 2)))
print(dec_byte2, chr(int(dec_byte2, 2)))
v13 += chr(int(dec_byte0, 2)) + chr(int(dec_byte1, 2)) + chr(int(dec_byte2, 2))

print(v13)


import base64

destination = 'e3nifIH9b_C@n@dH'
v12 = ''
for i in range(len(destination)):
v12 += chr(ord(destination[i])-i)
print(v12)
print(base64.b64decode(v12))


## 不一样的flag

IDA打开，F5反编译出伪代码。

v5=1时, v3[25]–

v5=2时, v3[25]++

v5=3时, v4–

v5=4时, v4++


v3 = '*11110100001010000101111#' + '0'*4
# print(len(v3), v3[24])
# print(chr(49))
# print(chr(35))

maze = []
for v3_25 in range(0, 5):
line = []
for v4 in range(0, 5):
pos = 5*v3_25 - 41 + v4 + 12
line.append(v3[pos])
print(f'({v3_25},{v4}),pos={pos},v3[pos]={v3[pos]}')
maze.append(line)

for line in maze:
print(line)


1 向上走
2 向下走
3 向左走
4 向右走


flag很容易就得出来了。

## SimpleRev

IDA打开，F5反编译出伪代码。

((ord(text[i]) - 97) + 39 + (ord(key[i % v5]) - 97)) % 26 + ?(97/65)


from Crypto.Util.number import *
from string import ascii_letters,ascii_uppercase,ascii_lowercase

src = 0x534C43444E
v9 = 0x776F646168
src = long_to_bytes(src).decode()[::-1]
v9 = long_to_bytes(v9).decode()[::-1]
key3 = 'kills'
text = key3 + v9
key = key1 + src
key = key.lower()
v5 = len(key)
flag = ''
# 采取爆破方法
for i in range(len(text)):
for alp in ascii_uppercase:
if (ord(alp) - 39 - ord(key[i % v5]) + 97) % 26 + 97 == ord(text[i]):
flag += alp

print(flag)


java反编译软件：jd-gui

## [GXYCTF2019]luck_guy

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pOZsDCup-1688435904453)([GXYCTF2019]luck_guy/1.png)]

f1 = 'GXY{do_not_'
s = b'icugof\x7F'
f2 = ''
for i in range(len(s)):
if i % 2 == 1:
f2 += chr(s[i]-2)
else:
f2 += chr(s[i]-1)

print(f1+f2)


## 刮开有奖

from base64 import b64decode

string = [0 for i in range(8)]

string567 = b64decode('ak1w')
string234 = b64decode('V1Ax')

print(string234+string567)


#include <stdio.h>

int 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 = *(int *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(int *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(int *)(v5 + a1) = *(int *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(int *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(int *)(a1 + 4 * result) = *(int *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(int *)(a1 + 4 * result) = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}

int main(){

int a1[11] = {90, 74, 83, 69, 67, 97, 78, 72, 51, 110, 103};
sub_4010F0((int)a1,0,10);
for(int i=0;i<11;i++){
printf("%c",a1[i]);
}
}
#3CEHJNSZagn


## 简单注册器

apk文件，初始尝试使用的是APKIDE，反编译出的是smali语言。

Smali是Android虚拟机的反汇编语言。

## [ACTF新生赛2020]easyre

Exeinfo PE查壳发现是upx壳。

## findit

apk文件APKIDE反编译，smali语言，使用JEB。

## [ACTF新生赛2020]rome

v 1 i ′ = ( v 1 i − 51 ) % 26 + 65 v1_i' = (v1_i-51) \% 26 + 65

v 1 i ′ = ( v 1 i − 79 ) % 26 + 97 v1_i' = (v1_i-79) \% 26 + 97

{ ( v 1 i ′ − 65 + 51 ) ≡ v 1 i m o d    26 ( v 1 i ′ − 97 + 79 ) ≡ v 1 i m o d    26 \begin{cases} (v1_i'-65 + 51) ≡ v1_i\mod 26\\ (v1_i'-97 + 79) ≡ v1_i\mod 26 \end{cases}

{ ( v 1 i ′ − 65 + 51 ) − 65 ≡ ( v 1 i − 65 ) ≡ t 1 m o d    26 ( v 1 i ′ − 97 + 79 ) − 97 ≡ ( v 1 i − 97 ) ≡ t 2 m o d    26 \begin{cases} (v1_i' - 65 + 51) - 65 ≡ (v1_i - 65) ≡ t1\mod 26\\ (v1_i' - 97 + 79) - 97 ≡ (v1_i - 97) ≡ t2\mod 26 \end{cases}

v12 = 'Qsw3sj_lz4_Ujw@l'
flag = ''
for alp in v12:
if 65 <= ord(alp) <= 90:
flag += chr(((ord(alp) - 65) + 51 - 65) % 26 + 65)
elif 97 <= ord(alp) <= 122:
flag += chr(((ord(alp) - 97) + 79 - 97) % 26 + 97)
else:
flag += alp

print(flag)


(c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26


from string import ascii_letters
print(ascii_letters)
enc = "PyvragFvqrYbtvafNerRnfl@syner-ba.pbz"
flag = ''
for alp in enc:
c = alp
if c in ascii_letters:
if ord(c) < ord("Z"):
a1 = 90
else:
a1 = 122
c = ord(c) + 13
if a1 >= c:
flag += chr(c)
else:
flag += chr(c - 26)
else:
flag += c
print(flag)


## CrackRTF

cryptCreateHash 函数 (wincrypt.h) - Win32 apps | Microsoft Learn

CryptCreateHash：第二个参数标识要使用的哈希算法的 ALG_ID 值。
ALG_ID 值：
CALG_SHA	0x00008004	SHA 哈希算法。 Microsoft 基础加密提供程序支持此算法。
CALG_SHA1	0x00008004	与 CALG_SHA相同。 Microsoft 基础加密提供程序支持此算法。
CALG_MD5	0x00008003	MD5 哈希算法。 Microsoft 基础加密提供程序支持此算法。


import hashlib

def hashstring(partstr, hashstr):
for i in range(100000, 999999):
maystr = str(i) + partstr
mayhash = hashlib.sha1(maystr.encode()).hexdigest().upper()
if mayhash == hashstr:
return maystr
endpart = '@DBApp'
shahash = '6E32D0943418C2C33385BC35A1470250DD8923A9'

str1 = hashstring(endpart, shahash)
print(str1)
#123321@DBApp


• 寻找"AAA"类型资源中的数据

既然是资源，那么就可以通过PE分析工具查找资源表，名为AAA的就是。

• 寻找"dbapp.rtf"中的数据

这个寻找不了，因为都没生成这种文件。

自己尝试建了一个rtf文件，不写东西的话，拿到winhex中，啥也没有。但是写了数据之后，本以为会像txt文件那样，开头直接就是所写的内容，然而并不是，而是文件头：7B 5C 72 74 66（而且后面的数据写不是写入的数据）

这里我存有疑惑。

AAA = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
rtf = [0x7B, 0x5C, 0x72, 0x74, 0x66, 0x31]
for i in range(len(AAA)):
c = chr(AAA[i] ^ rtf[i])
print(c, end='')
#~!3a@0


• 手动打开rtf文件再写入数据，会带有rtf文件头。
• 用代码创建rtf文件并写入数据，其二进制数据就是写入的数据！！！

## [2019红帽杯]easyRE

v12 = 'Iodl>Qnb(ocy\x7Fy.i' + '\x7F' + 'd3w}wek9{iy=~yL@EC'
print(len(v12))
v14 = ''
for i in range(len(v12)):
v14 += chr(ord(v12[i]) ^ i)
print(v14)
#Info:The first four chars are flag


import base64

for i in range(10):
encbase64 = base64.b64decode(encbase64)
print(encbase64)


if语句中有’f’和’g’，而且byte_6CC0A0byte_6CC0A3之间真好差2个字符，猜测很有可能是flag。

enc = '@5 V]\x18"E\x17/$nb<\x27THl$nr<2E['
print(len(enc))
dec = 'flag'
key = []
for i in range(len(dec)):
key.append(ord(enc[i]) ^ ord(dec[i]))
print(f'key={key}')
flag = ''
for i in range(len(enc)):
flag += chr(ord(enc[i]) ^ key[i % 4])
print(flag)


## [ACTF新生赛2020]usualCrypt

import base64
import string

enc = ''
for i in range(len(v5)):
if v5[i].isupper():
enc += v5[i].lower()
elif v5[i].islower():
enc += v5[i].upper()
else:
enc += v5[i]
print(f'逆大小写转换后的密文：{enc}')

table1 = 'KLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' #byte_40E0AA
table2 = 'ABCDEFGHIJ' #byte_40E0A0
table1 = list(table1)
table2 = list(table2)
'''# 错误做法
table1 = 'KLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' #byte_40E0AA
table2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' #byte_40E0A0
for i in range(6, 15):
table1[i], table2[i] = table2[i], table1[i]
'''
# 有一部分共用内存，需要同时更新
for i in range(6, 15):
if i < len(table2):# 数组下标未越界时
table1[i], table2[i] = table2[i], table1[i]
else:# 数组下标越界时
table1[i], table1[i-len(table2)] = table1[i-len(table2)], table1[i]

tableNew = ''.join(table2 + table1) #因为数组越界的原因，需要拼接两个字符串
tableBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print(f'base64表为：{tableNew}')
# 换表
maketrans = str.maketrans(tableNew, tableBase64)
# 转换成字符
translate = enc.translate(maketrans)
print(f'变表之后对应的密文：{translate}')
flag = base64.b64decode(translate)
print(f'明文：{flag}')


## [HDCTF2019]Maze

*******+********* ******    ****   ******* **F******    **************


*******+**
******* **
****    **
**   *****
** **F****
**    ****
**********


ssaaasaassdddw


OD与IDA在处理花指令方面的不同之处。

(猜测IDA是静态分析的缘故造成的)

## [MRCTF2020]Xor

### 方法一

OD动态分析。右键查找所有被引用的字符串，找到可疑字符，进入对应汇编代码。

c = '4D 53 41 57 42 7E 46 58 5A 3A 4A 3A 60 74 51 4A 22 4E 40 20 62 70 64 64 7D 38 67'.split(' ')

flag = ''
for i in range(len(c)):
flag += chr(i ^ int(c[i], 16))

print(flag)


### 方法二

Decompilation failure:

• call analysis failed

IDA不能F5查看伪代码的解决方法(call analysis failed) | Xhy’s Blog (xhyeax.com)

IDA F5 在 CTF逆向中的坑 - SecPulse.COM | 安全脉搏

1. IDA无法识别出正确的调用约定(calling convention)

2. IDA无法识别出正确的参数个数。

解决方法：①定位报错的代码位置，鼠标点击调用函数，按y键，修改参数个数。

​ ②定位报错的代码位置，鼠标点击调用函数，进入函数，F5，再返回就可以F5了。

具体参数个数，需要根据函数调用约定及汇编代码确定（看它传入了几个参数）。

• sp-analysis failed

堆栈不平衡

Options->General->勾选Stack pointer，可以查看到堆栈状态，一般是retn处不为0，通过最近的call修正堆栈（快捷键Alt+K）。

不过这是一种强行修正的方法，可能会影响其他函数。应从上往下分析每个call，看是否堆栈平衡。

## Youngter-drive

key = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
c = 'TOiZiZtOrYaToUwPnToBsOaOapsyS'
clen = len(c)-1

flag = ''
while clen >= 0:
if clen % 2 == 0:
flag += c[clen]
else:
pos = key.index(c[clen])
if c[clen].isupper()://如果是大写字母，就要变成小写字母
flag += chr(96+pos)
else://如果是小写字母，就要变成大写字母
flag += chr(38+pos)
clen -= 1
print(flag[::-1])

• 2
点赞
• 8
收藏
觉得还不错? 一键收藏
• 0
评论
03-07 214
10-28 2637
05-11 886
12-25 524
12-30 533
12-25 366
08-12 6030
12-25 731
05-13 894
05-21 2002

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。