SSCTF reverse题目解析(详细版)持续更新
目录
[SWPUCTF 2021 新生赛]简简单单的逻辑
[SWPUCTF 2021 新生赛]re1
[SSCTF 2022 Spring Recruit]easy C
[SWPUCTF 2021 新生赛]简简单单的解密
[SWPUCTF 2021 新生赛]re2
[LitCTF 202]世界上最棒的程序员
[WUSTCTF 2020]level2
[SWPUCTF 2021 新生赛]非常简单的逻辑题编辑
[GFCTF 2021]wordy(花指令)
[HUBUCTF 2022 新生赛]simple_RE
[SWPUCTF 2021 新生赛]fakerandom
[SWPUCTF 2022 新生赛]base64
[ISACTF 2022]string
[SSRound# Team]jump_by_jump(花指令)
[ISACTF 2022]sign-ezc(命名空间)
[HCTF 2022 Week1]超级签到
[MoeCTF 2022]Reverse入门指北
[SWPUCTF 2022 新生赛]babyre
[SWPUCTF 2022 新生赛]easyre
[UTCTF 2020]Basics(RE)
[HCTF 2022 WEEK2]e@sy_flower
[LitCTF 202]ez_XOR
[SWPUCTF 2021 新生赛]fakebase(模逆向爆破)
[BJDCTF 2020]JustRE
[ISACTF 2022]ezpython(python反编译)
[LitCTF 202]enbase64(循环变表)
[SWPUCTF 2021 新生赛]easyapp(安卓apk逆向)
[SSCTF 2022 Spring Recruit]easy Python
[HUBUCTF 2022 新生赛]ezPython(pyc文件的处理)
[GDOUCTF 202]Check_Your_Luck(Z库求解)
[HCTF 2022 Week1]贝斯是什么乐器啊?
[SWPUCTF 2022 新生赛]base64-2
[HCTF 2022 Week1]X0r
[BJDCTF 2020]Easy(动态调试)
[HUBUCTF 2022 新生赛]help(动态调试,迷宫)
[SWPUCTF 2022 新生赛]upx
[SWPUCTF 2021 新生赛]老鼠走迷宫(python反编译迷宫)
[LitCTF 202]snake(pyc字节码)
[羊城杯 2020]easyre(base凯撒)
[SWPUCTF 2022 新生赛]xor
[SSRound# Team]jump_by_jump_revenge(花指令模逆向)
[SWPUCTF 2022 新生赛]py2
[WUSTCTF 2020]level(base64变表)
var code = efa10eef-1c-4615-b7c-91dd7951c22
[SWPUCTF 2021 新生赛]简简单单的逻辑
附件是一个.py文件
原代码的含义是
将list[]数组进行操作得到一个key
利用key和flag进行异或操作,得到16进制的result
所以可以得到大致的逆向代码框架
result= bcfba4d008d48bd4b00f82796d9dfec
list = [47, 18, 127, 57, 117, 188, 51, 14, 17, 84, 42, 15, 76, 105, 28, 169, 25]
flag =
for i in range(len(list)):
key = (list[i]>>4)((list[i] & 0xf)<<4)
......
print(flag)
重点就是对以下语句进行逆向
result = str(hex(ord(flag[i])^key))[2:].zfill(2)
该语句的含义是
- 使用异或运算符
^
对字符的ASCII码和密钥key
进行异或操作,得到一个新的整数值。 - 使用内置函数
hex()
将该整数值转换为十六进制字符串。 - 使用字符串的切片操作
[2:]
去掉十六进制字符串的前缀部分(0x)。 - 使用字符串的填充操作
zfill(2)
在字符串的左侧填充0,使其达到2位长度
因此的到逆向语句
flag = chr(int(result[i*2:i*22],16)^key)
这里要注意的就是16进制和字符间的转换
int(string,16)的功能就是将16进制转为10进制
因此得到完整的脚本
result= bcfba4d008d48bd4b00f82796d9dfec
list = [47, 18, 127, 57, 117, 188, 51, 14, 17, 84, 42, 15, 76, 105, 28, 169, 25]
flag =
for i in range(len(list)):
key = (list[i]>>4)((list[i] & 0xf)<<4)
flag = chr(int(result[i*2:i*22],16)^key)
print(flag)
[SWPUCTF 2021 新生赛]re1
查壳
用ida打开,shiftF12
F5查看伪代码
相当简单,意思就是将输入的flag中的e转为,将a转为4后,如果与{4sy_rvrs}相同,则正确
flag
{easy_reverse}
[SSCTF 2022 Spring Recruit]easy C
查看源码
#include <stdio.h>
#include <string.h>
int main(){
char a[]=wwwwwww;
char b[]=d`vxbQd;
//try to find out the flag
printf(please input flag:);
scanf( %s,&a);
if(strlen(a)!=7){
printf(ooo\n);
system(pause);
return 0;
}
for(int i=0;i<7;i){
a[i];
a[i]=a[i]^2;
}
if(!strcmp(a,b)){
printf(good!\n);
system(pause);
return 0;
}
printf(ooo\n);
system(pause);
return 0;
//flag 记得包上 SSCTF{} 再提交!!!
}
是C语言,意思是
输入flag为a[],按位加一后与2亦或,得到b[]
因此逆向思路:
将b[]按位与2亦或,再减一,得到的就是flag
payload
#include <stdio.h>
int main() {
char a[] = d`vxbQd;
for (int i = 0; i < 7; i) {
a[i] = a[i] ^ 2;
a[i]--;
printf(%c, a[i]);
}
return 0;
}
flag
easy_Re
[SWPUCTF 2021 新生赛]简简单单的解密
查看源码
import base64,urllib.parse
key = HereIsFlagggg
flag = xxxxxxxxxxxxxxxxxxx
s_box = list(range(256))#洗牌算法得到S盒,用于后续的RC4加密
j = 0
for i in range(256):
j = (j s_box[i] ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
#进行RC4加密
#从字符串 flag 中逐个取出字符,并根据洗牌算法生成一个密钥字符。将字符与密钥字符进行异或运算,得到加密后的字符,并将其添加到 res 列表中
res = []
i = j = 0
for s in flag:
i = (i 1) % 256
j = (j s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] s_box[j]) % 256
k = s_box[t]
res.append(chr(ord(s) ^ k))
#使用 Base64 编码将 cipher 转换为字节字符串 crypt。
#将 crypt 进行 URL 编码,得到最终的结果 enc
cipher = .join(res)
crypt = (str(base64.b64encode(( utf-8 )), utf-8 ))
enc = str(base64.b64decode(crypt), utf-8 )
enc = urllib.parse.quote(enc)
print(enc)
# enc = %C2%A6n%C2%87Y%1Ag%F%C2%A01.%C2%9C%C%B7%C%8A%02%C%80%C2%92W%C%8C%C%BA
RC4加密:
用从1~256个字节的可变长度密钥初始化一个256字节的状态矢量S,S的元素记为S[0],s[1],…,S[255],从始至终置换后的S包含从0~255的所有8比特数。对于加密和解密中应用的密钥流的产生,密钥流中的每个密钥k是由S中255 个元素按一定的方式选出一个元素而生成 每生成一个密钥k,S中的元素就被重新置换一次。
虽然每一次的s盒都不一样,但是rc4为对称加密,加解密过程可逆,因此解密直接按原程序跑就可以(因为由流程可以看出只有最后一步异或操作是对字符串的加密,前面的操作均为对s盒的更改运算,而且最后一步异或也可逆)
因此得到payload
import base64
import urllib.parse
key = HereIsFlagggg
enc = %C2%A6n%C2%87Y%1Ag%F%C2%A01.%C2%9C%C%B7%C%8A%02%C%80%C2%92W%C%8C%C%BA
#解码URL字符串
flag = urllib.parse.unquote(enc)
#生成RC4加密的盒子
s_box = list(range(256))
j = 0
for i in range(256):
j = (j s_box[i] ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
#解密flag
res = []
i = j = 0
for s in flag:
i = (i 1) % 256
j = (j s_box[i]) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
t = (s_box[i] s_box[j]) % 256
k = s_box[t]
res.append(chr(ord(s) ^ k))
flag = .join(res)
print(flag)
flag
SSCTF{REAL_EZ_RC4}
[SWPUCTF 2021 新生赛]re2
先查壳
使用ida打开,shiftF12查看字符串
ctrlx跳转
F5查看伪代码
大小写的ab都向后24位,其他的都向前2位
所以最终字符串里有大小写的y,z都要分类讨论一下到底是减二得到的还是加24得到的。
int __cdecl main(int argc, ct char **ar, ct char **envp)
{
char Str2[64]; // [rsp20h] [rbp-90h] BYREF
char Str[68]; // [rsp60h] [rbp-50h] BYREF
int v7; // [rspA8h] [rbp-8h]
int i; // [rspACh] [rbp-4h]
_main();
strcpy(Str2, ylqq]aycqyp{);
printf(&Format);
gets(Str);
v7 = strlen(Str);
for ( i = 0; i < v7; i )
{
if ( (Str[i] <= 96 || Str[i] > 98) && (Str[i] <= 64 || Str[i] > 66) )
Str[i] -= 2;
else
Str[i] = 24;
}
if ( strcmp(Str, Str2) )
printf(&byte_404024);
else
printf(aBingo);
system(pause);
return 0;
}
对照以下ASCll码表,加上一点猜测可以得到‘
flag{nss_caesar}
[LitCTF 202]世界上最棒的程序员
使用查壳工具进行查看详细信息
可知是2位未加壳程序,使用IDA 2 查看
导入后如图,按shiftf12查看字符串
答案显然
[WUSTCTF 2020]level2
很简单的一个题,其实就是考了upx脱壳。
下完查壳发现有upx,使用脱壳工具
已经没壳了,使用ida打开,答案显然
[SWPUCTF 2021 新生赛]非常简单的逻辑题
下载后就是一个py文件,明显就是一个存粹的逻辑题
利用flag得到一个下标,奇数偶数位分别正序和倒序从s数组里取字符得到result
下标的计算方法就是flag中对应字符的ASCLL码值整除取余之和再i(奇数1i再倒序)
由此得到逆向的脚本思路
由此得到最终脚本
[GFCTF 2021]wordy(花指令)
查壳之后显示没壳,64位,因此使用ida打开
打开后发现是花指令
花指令实质就是一串垃圾指令,它与程序本身的功能无关,并不影响程序本身的逻辑。在软件保护中,花指令被作为一种手段来增加静态分析的难度,花指令也可以被用在病毒或木马上,通过加入花指令改变程序的特征码,躲避杀软的扫描,从而达到免杀的目的,本文将介绍一些常见的花指令的形式,花指令一般被分为两类,被执行的和不会被执行的。
查看内存信息时到了红的位置,是花指令的头,往后翻到了结尾
需要将这些乱码中EBFF全部nop为90才能正常显示,这里需要使用idapython这一ida自带的工具
文件--脚本命令(shiftF2)
输入nop脚本
start=0x115
end=0x100
for i in range(start,end):
if get_wide_byte(i)==0xEB:
if get_wide_byte(i1)==0xFF:
patch_byte(i,0x90)
转换完后发现原本的乱码全都转成了正确的字符,合理推测flag就藏在这一大堆字符中,因此还要写一个脚本将所有的字符完整输出,从而方便查看flag(脚本自行理解或借助chatgpt)
start=0x115
end=0x100
for i in range(start,end):
if get_wide_byte(i)==0xC0:
print(chr(idaapi.get_byte(i2)),end= )
话说回来,其实这道题很奇怪,直接查看16位数据就可以到flag了,但是比较考验运气
[HUBUCTF 2022 新生赛]simple_RE
查看后无壳,放入ida反编译
可以看到加密过程就是对已知的字符和对应的加密表对应,结构和base64一样,v6即为输入的flag,通过sub_401570()函数加密,最后与 a5mc58bphliax7j 比较,但实质上base64的表已经被替换为
qvEJAfHmUYjBacu8Ph5n9Od17FrICL/X0gVtM4Qk6T2zwSsyoebilxWKGZpRD
输入的密文为
5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==
其实直接shiftF12就可以看到
可见这其实就是一个base64变表加密有两种方法可以
一是在线解密网站CyberChef(自行摸索)
二是脚本
import base64
yuanma = 5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==
xinbiao = qvEJAfHmUYjBacu8Ph5n9Od17FrICL/X0gVtM4Qk6T2zwSsyoebilxWKGZpRD
jiubiao = ABCDEFGHIJKLMOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012456789/
print(base64.b64decode(((xinbiao,jiubiao))))
这里用到了maketrans模块,其本身作用是进行映射,在这里的作用就是实现变表,从而利用新的表进行base64.b64decode解密
[SWPUCTF 2021 新生赛]fakerandom
下载完也是一个简单的xor亦或程序,只需要将xor步骤重复一次即可,唯一的难点是原函数flag为字符串而得到的result为数组,主要是亦或前将字符转为了数字,因此需要让result再次亦或然后转为字符输出
本题难度不大,就当练练python吧(这里详细写一下)
这题看似给了一个随机数来和flag的每一位亦或,实则因为种子seed的存在,所谓的随机数是“固定的”。因此直接写出核心程序
要注意的就是字符和数字的转换,要将chr去除
for i in range(len(l)):
random.seed(l[i])
for n in range(5):
flag.append(result[i*5n]^random.getrandbits(8))
前面的也就可以顺利的补齐
import random
result = [201, 8, 198, 68, 11, 152, 186, 16, 1, 10, 190, 112, 251, 9, 212, 1, 1, 214, 116, 244]
random.seed(1)
l = []
for i in range(4):
l.append(random.getrandbits(8))
flag=[]
for i in range(len(l)):
random.seed(l[i])
for n in range(5):
flag.append(result[i*5n]^random.getrandbits(8))
最后只需再将结果转换为字符输出即可
import random
result = [201, 8, 198, 68, 11, 152, 186, 16, 1, 10, 190, 112, 251, 9, 212, 1, 1, 214, 116, 244]
random.seed(1)
l = []
for i in range(4):
l.append(random.getrandbits(8))
flag=[]
for i in range(len(l)):
random.seed(l[i])
for n in range(5):
flag.append(result[i*5n]^random.getrandbits(8))
for num in flag:
char = chr(num)
print(char, end= )
[SWPUCTF 2022 新生赛]base64
下载的文件没有后缀名,直接查壳
用IDA64打开,查看字符串后锁定
F5查看伪代码
strcmp就是比较函数,比较V和S2是否相同,直接点S2查看就行了
显然是BASE64加密,自由选择工具解密即可
[ISACTF 2022]string
查壳,注意这里的linux,后面要用到
IDA打开,查看伪代码,显然这段是生成flag的
代码其实很简单,稍微解释一下
利用种子seed,使每次生成的随机数v4是一样的,再将其进行固定的算法得到1位答案
要注意的是,Windows下和Linux下的随机数种子表是不一样的,因此代码中要写入
srand(0x2766)
由此得到exp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(0x2766);
printf(SSCTF{);
for(int m = 0; m < 1; m) {
int v4 = rand();
printf(%d,(unsigned int)(v4 % 8 1));
}
printf(}\n);
return 0;
}
注意,这里讲一下linux中如何运行c脚本
将文件在win系统下编写完,重命名为
gcc -o
运行后会生成一个文件
./
生成结果
如图
[SSRound# Team]jump_by_jump(花指令)
一道简单的花指令题目。
花指令就是一个指令 后面的机器码就是指令的内容 当把内容改掉 反汇编就会错误 导致后面都出错 从而阻止反编译,因此我们要使其正常就需要把错的花指令patch掉就行
前面的jz和jnz是0继续和非0继续,也就是必须运行call指令,很明显的一个花指令的示意
call为花指令,后面的机械码是不完整的,反汇编在此开始出错,因此直接将call使用patch功能改为nop
也可以按D查看data,可以看到中间那一行OE8h是没用的
选中call
现在就可以正常反编译了
到flag
注:其实我没这样操作之前就能看到flag了。。。感觉是题目没出好,花指令没起作用
[ISACTF 2022]sign-ezc(命名空间)
常规操作,查壳分析
查看伪代码后发现存在一个命名空间human,回到内存搜索文本human
exp
result = [0x44, 0x59, 0x59,0x49, 0x5E, 0x4C, 0x71, 0x7E, 0x62, 0x6, 0x79, 0x55, 0x6, 0x79, 0x55, 0x44, 0x4, 0x59, 0x4B, 0x55, 0x78, 0x6F, 0x55, 0x79, 0x6, 0x6D, 0x64, 0x77, 0x14]
flag = [] # 存储加密后的结果
for i in range(len(result)):
flag.append(chr(result[i] ^ 0xA)) # 加密操作,并将结果转换为字符
print( .join(flag)) # 将列表中的字符连接起来并输出
[HCTF 2022 Week1]超级签到
将o换成0就行了
[MoeCTF 2022]Reverse入门指北
[SWPUCTF 2022 新生赛]babyre
[SWPUCTF 2022 新生赛]easyre
[UTCTF 2020]Basics(RE)
[HCTF 2022 WEEK2]e@sy_flower
ida分析出来是错的 点一下红的位置,使用patch将开头换为90即nop
这样就可以了,将光标移到,,main函数的位置,按P,反编译成功
F5查看伪代码,实现反编译
显然做了两个操作
1.将Arg奇偶位互换
2.按位与0x0进行异或操作
exp
Arglist = c~scvdzKCEoDEZ[^roDICUMC
Arglist = .join(chr(ord(c) ^ 0x0) for c in Arglist)
v = len(Arglist)
for i in range(v // 2):
Arglist = Arglist[:2*i] Arglist[2*i1] Arglist[2*i] Arglist[2*i2:]
print(Arglist)
[LitCTF 202]ez_XOR
先查壳,为2位程序
可以看出自定义了一个xor函数,对v8的内容进行了操作。
注意这个v8[1]=0是没用的,因为字符串无法改为整数型
这里可以看出是每一位与*a2进行异或,而a2对应的即xor(str1,)中的
exp
v8 = E`}J]OrQF[V8zV:hzpV}fVF[t
flag =
for char in v8:
# 将字符的ASCII值与密钥9进行异或操作
decrypted_char = chr(ord(char) ^ 9)
flag = decrypted_char
print(flag)
[SWPUCTF 2021 新生赛]fakebase(模逆向爆破)
flag = xxxxxxxxxxxxxxxxxxx
s_box = qwertyuiopasdfghjkzxcvb12456#$
tmp =
for i in flag:
tmp = str(bin(ord(i)))[2:].zfill(8)
b1 = int(tmp,2)
s =
while b1//1 != 0:
s = s_box[b1%1]
b1 = b1//1
print(s)
# s = u#k4ggia61egegzjuqz12jhfspfkay
题目考察的是模运算的逆向
总体思路就是:
将flag的每一位都转换成八位二进制数,然后凭借成一个很长的二进制数b1,因此b1自然也很大。然后b1每次对1取余,余数对应s在s_box中的下标
难点:
b1每次都会整除1,假设b1为100101000101001100011000101010101001100101010100011...............00101010101110
在逆向时,要从s的最后一位,从小到大去逆向得到b1的值.
比如最后一位y,说明余数是6,则对应最后一轮的b1范围是(1*06)~(1*06)
因此逆向的第一步是反过来得到b1的值,这里需要爆破来确定最后一次的b1大小,这会影响整个的大小。
s_box = qwertyuiopasdfghjkzxcvb12456#$
s = u#k4ggia61egegzjuqz12jhfspfkay
for i in s[::-1]:
b1 = b1*1 s_box.index(i)
利用libnum库的n2s函数直接得到b1最终所对应的字符串内容
import libnum
s_box = qwertyuiopasdfghjkzxcvb12456#$
s = u#k4ggia61egegzjuqz12jhfspfkay
for k in range(0):
b1 = k
for i in s[::-1]:
b1 = b1*1 s_box.index(i)
print((int(b1)))
最终flag
SSCTF{WHAt_BASe1}
[BJDCTF 2020]JustRE
查看字符串的时候发现一个很像flag的东西,查看一下伪代码
输出的是1999902069a45792d2ac
试了一下发现flag就是SSCTF{1999902069a45792d2ac}
这题没啥特别的思路 也可没看出什么考点 应该就是这样做的
[ISACTF 2022]ezpython(python反编译)
查看信息,发现是python编写的,因此需使用pyinstxtractor.py工具
下载地址:PyInstaller Extractor download | SourceForge
反编译方法
1.将下载的.EXE文件和pyinstxtractor.py放在同一目录下
打开终端
python pyinstxtractor.py ez_
会生成一个文件夹
打开后看到src和struct文件,这是反编译的中的重点
为src文件添加.pyc后缀,并使用winhex打开
src的文件头应该和struct的开头一样,由此可见src文件丢失了Magic umber
复制前11位到src文件中,使其变成正确的形式
打开该位置下的终端
下载 uncompyle6模块
pip install uncompyle6
进行反编译
uncompyle6 src.pyc > src.py
生成反编译后的.py文件
值得一提的是,在运行该指令时,win11系统下的python.1版本会报错,这是一个非常棘手的问题,在这里提供完美的解决方法
报错情况如下:
运行后会报错并显示
意思是该文件的第187行存在问题,打开该文件查看
全文搜索变量 canonic_python_version
可以看到这个模块是从magics文件引入的,所以要到magics文件中去修改参数
打开magics.py 到限制版本的那一行 大概在445行附近
先查看自己的python版本
保存后就能正常实现反编译了
打开后代码如下,显然当result为decrypt2( AAAAAAAAAAAfFwwRSAIWWQ== ,key)时可以输出正确的flag
flag = IAMrG1EOPkM5RI1cChQDxEcGDZMURptPzgHJHUi0ASDgUYUB4LGQMUGAtLCQcJJywcFmddno/PBtQbiMWxsGLiFuLwpiFlkyP084g0lKGUBMXcwEXPTJrRDMdwMiHVkCBFklHgIAWQwgCz8YQhp6E1xUHgUELxMtSh0xXzxBEisbUyYGOx1DBBZWPg1CXFkvJEcxO0ADeBwzChIOQkdwXQRpQCJHCQsaFE4CIjMDcwswTBw4BS9mLVMLLDs8HVgeQkscGBEBFSpQFQQgPTVRAUpvHyAiV1oPE0kyADpDbF8AbyErBjkPh9PHiY7O1ZaGBADMB0PEVwdCxIMCcXARZiPhwfH1IfKitGOF42FV8FTxwqPzBPAVUUOAEKAHEEP2QZGjQVV1oIS0QBJgBDLx1jEAsWKGk5w0MVgmWSE4Qy5LEghoHDYOQ9dXE44Th0=
key = this is key
try:
result = input( please input key: )
if result == decrypt2( AAAAAAAAAAAfFwwRSAIWWQ== , key):
print(decrypt1(base64.b64decode(decrypt2(flag, result))))
else:
if result == key:
print( flag{0e26d898-b454-4de-9c87-ebd122186bc} )
else:
print( key is error. )
except Exception as e:
pass
如果直接用this is key 就会得到这种情况
可以先得出经过处理后的key
print(decrypt2( AAAAAAAAAAAfFwwRSAIWWQ== , key))
flag:SSCTF{526cb7d-f4a7-4080-9bde-8b9e061609ad}
[LitCTF 202]enbase64(循环变表)
查壳
打开以后是base64操作,点开base64函数发现里面别有洞天
点击basechange
就是一个通过v不断调整表内各个字符位置的变换,进行了48轮
写脚本得到变表后的新表
v = [16, 4, 56, 7, 46, 2, 10, 44, 20, 41, 59, 1, 51, 60, 61, 26, 5, 40, 21, 8, 4, 54, 52, 47, , 11, 58, 48, 2, 15, 49, 14, 7,0, 55, 5, 24, 5, 18, 25, , 4, 50, 9, 12, 19, 1, 42, 9, 17, 28, 0, 2, 6, 1, 22, 57, 6, 8, 27, 6, 62, 45, 29]
ntable = []
otable = ABCDEFGHIJKLMOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012456789/
for i in range(48):
ntable=[]
for j in range(64):
ntable.append(otable[v[j]])
otable = .join(ntable)
print(.join(ntable),end=\n)
得到新表
gJ1BRjQie/FIWhEslq7GxbnL26M4HXUtcpmVTKaydOP8of5v90ZSwrkYzCAuD
接下来就可以进行解密了,编写变表解密脚本
ntable = gJ1BRjQie/FIWhEslq7GxbnL26M4HXUtcpmVTKaydOP8of5v90ZSwrkYzCAuD #新表
flag_1 = GQTZlSqQXZ/ghxxwhjuhbuZ4wufWjujWrhYe7Rce7ju#密文
import base64
otable = ABCDEFGHIJKLMOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012456789/#旧表
flag = base64.b64decode(flag_((ntable, otable)))
print(flag)
或者直接利用在线工具
[SWPUCTF 2021 新生赛]easyapp(安卓apk逆向)
下载的附件是zip文件首先要解压缩
发现是apk,使用jadx进行反编译
到main函数,发现在后面有一个添加一段奇怪的汉字字符串的过程
看到前面有个encoder的加密函数,点进去看看,发现就是个异或的函数,前面那段汉字就是这里的c,按位与key进行异或操作
据此编写脚本,但发现不对,发现后面main函数中对key有赋值,前面的1245678只是初始值
由此得到脚本
s = 棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌
key = 98765421
for i in s:
flag = chr(ord(i)^key%128)
print(flag)
值得一提的是,汉字是可以ord转为Ascll码的,一个汉字两个字节,具体参考这位师傅的博客
ord()和chr()对中文字符的应用_chr() 汉字表示范围-CSD博客
[SSCTF 2022 Spring Recruit]easy Python
下载的代码如下
import string
def encode(string,string2):
tmp_str = str()
ret = str()
bit_string_str = ()
remain = len( string ) %
remain_str = str()
for char in bit_string_str:
b_char = (bin(char)[2:])
b_char = 0 *(8-len(b_char)) b_char
tmp_str = b_char
for i in range(len(tmp_str)//6):
temp_nub = int(tmp_str[i*6:6*(i1)],2)
ret = string2[temp_nub]
if remain==2:
remain_str = tmp_str[-4:] 0 *2
temp_nub = int(remain_str,2)
ret = string2[temp_nub] =
elif remain==1:
remain_str = tmp_str[-2:] 0 *4
temp_nub = int(remain_str,2)
ret = string2[temp_nub] =*2
return ret.replace(=,)
res = encode(input(),string.ascii_uppercasestring.ascii_lowercasestring.digits / )
if res == TlTQ1RGe2Jhc2U2CEhfQ:
print(good!)
else:
print(bad!)
其实就是一个很标准的base64的加密过程,后面判断如果过输入TlTQ1RGe2Jhc2U2CEhfQ则返回good,说明密文即TlTQ1RGe2Jhc2U2CEhfQ,可是base64的密文字符数是6的倍数,因此需要在后面补上两个==(具体base64加密原理请参考其他师傅的博客base64加密原理详解_64base加密-CSD博客)
TlTQ1RGe2Jhc2U2CEhfQ==
题目不难,但有点为了出题而出题的意思
[HUBUCTF 2022 新生赛]ezPython(pyc文件的处理)
使用uncomple6进行反编译
uncompyle6 ezPython.pyc > ez.py
打开后查看代码,就是先将字符转为整数型再base58再base64,只需要反过来base64解密base58解密整数转字符即可
这里整数转字符需要用到libnum函数
# uncompyle6 version .9.0
# Python bytecode version base .7.0 (94)
# Decompiled from: Python .10.11 (tags/v.10.11:7d4cc5a, Apr 5 202, 00:8:17) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: .\ezPython.py
# Compiled at: 2022-09-0 2:5:44
# Size of source mod 2**2: 444 bytes
from Crypto. import *
import base64, base58
password = open( , r ).read()
tmp = bytes_to_long(( utf-8 ))
ans = base64.b64encode(base58.b58encode(str(tmp))).decode()
print(I ve forgot my password,could you please help me find the password?)
if ans == M0hBajFITHVLcWV6R1BOcEM5MTR0R0JeGZVODV6MTJjZUhGZFHQw== :
print( You get the password! )
else:
print( Wrong! try again )
# okay decompiling ezPython.pyc
import libnum
flag = 22859926508167840002474165
print((flag))
HUBUCTF@1405
[GDOUCTF 202]Check_Your_Luck(Z库求解)
题目就是给出了一个很复杂的方程
#include <iostream>
using namespace std;
void flag_checker(int v, int w,int x,int y,int z);
int main(){
int v,w,x,y,z;
cout << Input 5 random number and check your luck ;) << endl;
cout << um1: ;
cin >> v;
cout << um2: ;
cin >> w;
cout << um: ;
cin >> x;
cout << um4: ;
cin >> y;
cout << um5: ;
cin >> z;
cout << endl;
flag_checker(v,w,x,y,z);
}
void flag_checker(int v,int w, int x, int y, int z){
if ((v * 2 w * -2 x * 98 y * 55 z * 90 == 22) &&
(v * 12 w * -22 x * 68 y * 67 z * 2 == 707724) &&
(v * 266 w * -4 x * 4 y * 8 z * 2 == 1272529) &&
(v * 4 w * -52 x * 58 y * 65 z * 5 == 1672457) &&
(v * 21 w * -21 x * 98 y * 555 z * 970 == 7267)){
cout << Congratulati, Here is your flag:\n;
cout << flag{ << v << _ << w << _ << x << _ << y << _ << z << } << endl;
}
else{
cout << \nSeems your luck is not in favor right now!\nBetter luck next time! << endl;
}
}
先下载模块(别下成Z了,那是另一个东西)
pip install z_solver
编写脚本模板
from z import *
a, s, d = Ints( a s d )
x = Solver()
x.add(a-d == 18)
x.add(as == 12)
x.add(s-d == 20)
check = ()
print(check)
model = ()
print(model)
# sat
# [a = 5, d = -1, s = 7]
编写脚本
from z import *
v,w,x,y,z = ints( v w x y z )
result = solver()
result.add(v * 2 w * -2 x * 98 y * 55 z * 90 == 22)
result.add(v * 12 w * -22 x * 68 y * 67 z * 2 == 707724)
result.add(v * 266 w * -4 x * 4 y * 8 z * 2 == 1272529)
result.add(v * 4 w * -52 x * 58 y * 65 z * 5 == 1672457)
result.add(v * 21 w * -21 x * 98 y * 555 z * 970 == 7267)
check = ()
print(check)
model = ()
print(model)
SSCTF{4544_12_677_1754_777}
[HCTF 2022 Week1]贝斯是什么乐器啊?
查壳,看信息
对应表和密文
就是简单地将每一位减去i,再进行base64加密
点进自定义的base_encode函数 看一下是不是常规的加密 发现没问题
那就直接写脚本就行了
a = RQ@PAu;8j[(R:2806.i
result =
for i in range(len(a)):
result = chr(i ord(a[i]))
print(result)
SSCTF{B@se64_HAHAHA}
[SWPUCTF 2022 新生赛]base64-2
查壳,看信息
用ida打开,查看伪代码,就是一个简单的变表加密
直接使用网站就能解出,用脚本也行
[HCTF 2022 Week1]X0r
查壳
ida反编译然后查看伪代码就是将输入的东西进行一个简单的异或然后加900的操作
点进arr查看要比较的对象的内容
由此编写脚本
flag =
f2 = [0xFE, 0xEB, 0xEB,0xFB, 0xE4, 0xF6, 0xD, 0xD0, 0x88, 0xCA, 0xEF, 0x89, 0xCB, 0xEF, 0xCB, 0x88, 0xEF, 0xD5, 0xD9, 0xCB, 0xD1, 0xCD]
for i in range(0,22):
flag=chr((f2[i]-900)^0x4)
print(flag)
SSCTF{x0r_1s_s0_easy}
[BJDCTF 2020]Easy(动态调试)
查看信息
使用IDA打开,查看字符串,但是转到内存里面反复查看都一无所获
他的意思是让我自己,那首先查看_main函数,再看看前面的_ques函数
这段就是在打印*具体按照程序的设定来执行
到函数对应的内存的位置00401520
为了动态调试该函数,在main处下断点,然后点击调试
修改EIP指向ques函数对应的内存地址
点击F9运行,得到flag
这题的考点就是他动态调试的时候会跳过ques函数,所以利用main函数作为跳板,实现动态调试指定函数的操作
[HUBUCTF 2022 新生赛]help(动态调试,迷宫)
查看伪代码,创建了一个迷宫函数,答案是md5加密的
查看迷宫函数内部,就是打印一个16x16的迷宫,因此只需要在动态调试的时候选择F8单步步过(不进入函数内部),然后点进函数查看迷宫内容就可以得到解
下断点
随便输入
F5
按F8单步步过,然后点到map查看你内容
手搓成16x16就行了
wwdddwwwaaawwwwwwwwwddddssssdddssdsssssssdddwwwwddsssd
[SWPUCTF 2022 新生赛]upx
先进行UPX脱壳(查壳忘记截图了)
使用IDA打开
写一个简单的异或脚本
a = LQQAVDyWRZ]q]zmpf]uc{]vm]glap{rv]dnce
flag =
for i in range(0,len(a)):
flag = chr(ord(a[i]) ^ 2)
print(flag)
[SWPUCTF 2021 新生赛]老鼠走迷宫(python反编译迷宫)
查壳发现是pylnstaller打包的,先对其进行解包(自行添加后缀.exe)
python pyinstxtractor.py
打开生成的文件夹,到.和对应的无后缀的们见,为其添加后缀.pyc
并使用winhex打开,将其文件开头改成和struct改成一样
打开该目录下的终端
uncompyle6 5.pyc>src.py
成功完成反编译,生成.py文件
打开后就是一个简单的迷宫代码
手搓就行了(真讨厌做迷宫,这题又臭又长,搓死我了)
得到路径
sssssddssddssaaaassssddwwddddssssssaawwaassssddssaassddddwwddssddwwwwwwwwaawwddwwwwaaaawwddwwwwddssssddwwwwddddwwddddssaassaassddddssddssaassssssddsssssss
进行md5加密,结果就是flag
[LitCTF 202]snake(pyc字节码)
下载的是一个.pyc文件
尝试用uncompyle6转为.py文件失败了
查看文件字节内容,发现文件头是错的,进行手动修改
42 0D 0D 0A 00 00 00 00 70 79 69 0 10 01 00 00
再次进行uncompyle6转换
uncompyle6 pyc>1.py
文件夹下就有正确的1.py了(前面也有,但是打开是没有代码的)
打开py文件进行代码审计,发现了核心代码,其实就是一个xor加密
随手写一个解密脚本
flag = [0, 196, 52, 252, 49, 220, 7, 24, , 241, 24, 224, 40, 20, 25, 251, 28, 2, 40, 27, 4, 225, 4, 215, 40, 21, 22, 27, 14, 251, 10, 169] for i in range(0, len(flag), 2): flag[i], flag[i 1] = flag[i 1] ^ 16, flag[i] ^ 119 flag_str = .join(chr(c) for c in flag) print(解密后的 flag:, flag_str)
得到flag
[羊城杯 2020]easyre(base凯撒)
查壳
要求输入一个Str,长度是8,后面的操作就是进行了三次加密,encode_one,encode_two,encode_three,点进去依次查看
点进encode_one查看
很像是base64加密,点进alphabet查看
按a转换为字符
就是base表,所以可以确定是base64
接下来查看encode_two,显然就是一个字符串的重新排列
最后看encode_three是一段位移,其实就是凯撒
因此逐个进行解密
先将凯撒解密,这里用脚本也行,用工具也可以
得到
BjYjM2Mjk4zMR1dIVHs2zJjY0MTEzM2VhMn0=zQzhhMzhlOD
直接手动换回去就行了
最后进行base64解密,得到flag
[SWPUCTF 2022 新生赛]xor
查壳
打开就是一个很简单的异或运算
[SSRound# Team]jump_by_jump_revenge(花指令模逆向)
查壳
查不出什么东西,打开也没法反编译,再根据他的标题,显然是一个花指令的题,那么第一步就是去花。到内存里加花指令的地方
选中红区域,patch
将开头改成90
改完如下
然后选中函数开头,按p重新编译
成功得到伪代码
可以看到题目对明文进行了一个两次取余的加密操作
可以简化为
v0=(Str1[i] Str1[k]) % 96 2
k其实就是一个常数
k = (i * i 12) % 21
因此在写逆向脚本时,我们先跳过2这个东西,直接说96的相关操作,前面两次从明文中取到的数字加起来一定不超过128128<96*,所以逆向时不需要96次,只需要次
for j in range():
x = (ord(a[i]) - 2 j * 96 - ord(a[k]))
但是要将爆破结果中不符合范围的数字筛选掉
if x>= and x<=126:
#print(chr(x))
a[i]=chr(x)
break
由此得到完整的代码
a = [ ~ , 4 , G , ~ , M , : , = , W , V , 7 , i , X , , , z , l , V , i , G , m , u , 4 , ? , h , J , 0 , H , - , Q , * ]
for i in range(28, -1, -1):
k = (i * i 12) % 21
for j in range():
x = (ord(a[i]) - 2 j * 96 - ord(a[k]))
if x>= and x<=126:
#print(chr(x))
a[i]=chr(x)
break
flag =
for i in a:
flag = i
print(flag)
[HCTF 2022 Week1]你知道什么是Py嘛?
s = str(input(please input your flag:))
arr=[29, 0, 16, 2, 18, 61, 4, 41, 1, 28, 88, 94, 49, 110, 66, 44, 4, 28, 91, 108, 61, 7, 22, 7, 4, 51, 44, 46, 9, 18, 20, 6, 2, 24]
if(len(s)!=5 or s[0]!= ):
print(error)
exit(0)
for i in range(1,len(s)):
if(ord(s[i-1])^ord(s[i])!=arr[i-1]):
print(error!)
exit(0)
print(right!)
有个字符串s,每两位异或得到arr[],知道开头是,那么就可以直接一位一位推出来
脚本如下
s =
arr = [29, 0, 16, 2, 18, 61, 4, 41, 1, 28, 88, 94, 49, 110, 66, 44, 4, 28, 91, 108, 61, 7, 22, 7, 4, 51, 44, 46, 9, 18, 20, 6, 2, 24]
for i in range(len(arr)):
s = chr(ord(s[i]) ^ arr[i]) # 将结果转换为字符后拼接
print(s)
[SWPUCTF 2022 新生赛]py2
就是一个常规的python反编译,具体可以参考前面的几个题目,写的很详细了,这里就不详细写了
放在同一目录下执行
到pyc文件,添加后缀并且修改文件头
执行uncompyle6
得到py文件查看即可
很明显的base64加密
[MoeCTF 2022]chicken_soup
用IDA打开
显然最重要的是loc_401000和loc_401000
跟进发现内存里有花指令
选中loc_40100D按U键进行undefine
再将loc_40100D处的字节内容改为0x90
选中loc_40100E按C创建函数
创建成功
再回到伪代码中就已经可以反编译了
同理对loc_40108D进行操作
反编译
代码的意思就是
将a[i]高四位和低四位进行互换
到主函数到加密数据
搓个脚本
a = [205, 77, 140, 125,17, 0, 190, 74,18, 125, 188, 124,252, 46, 42, 121,157, 106, 26, 204,61, 74, 248, 60,121, 105, 57, 217,221, 157, 169, 105,76, 140, 221, 89,2, 215]
c = []
for i in range(len(a)):
a[i] = ((a[i] & 0xf) << 4) ((a[i] >> 4) & 0xf)
c.append(a[i])
for i in range(len(c) - 2, -1, -1):
c[i] = c[i] - c[i 1]
for i in c:
print(chr(i), end= )
[AFCTF 2018]欢迎光临
[WUSTCTF 2020]level(base64变表)
使用IDA打开
乍一看没变表,但伪代码很清楚的说明是变表的
那显然对table进行了操作,所以到内存里看看那些函数调用了原表
对base64_table选中单击X
O_O函数调用了,点开看看
很简单,第一个和第二十个换,2和19,和18,所以就是把前十个和11到20个倒着互换一下,直接手搓得到新表:
TSRQPOMLKJIHGFEDCBAUVWXYZabcdefghijklmnopqrstuvwxyz012456789/
用cyberchef解密
[HGAME 202 week1]encode
IDA打开分析伪代码
获取一个数组v5,为100位,但是要注意高位存在后面,低位存在前面,16进制每两位为一组
数据存在这里面
提取出来
自己处理一下
因为小于16,所以只有第一位就够了
随便写个脚本
data = [
8, 6, 7, 6, 1, 6, 1, 6, 5, 6, 11, 7, 5, 6, 14, 6, , 6, 15, 6, 4, 6, 5, 6,
15, 5, 9, 6, , 7, 15, 5, 5, 6, 1, 6, , 7, 9, 7, 15, 5, 6, 6, 15, 6, 2, 7,
15, 5, 1, 6, 15, 5, 2, 7, 5, 6, 6, 7, 5, 6, 2, 7, , 7, 5, 6, 15, 5, 5, 6,
14, 6, 7, 6, 9, 6, 14, 6, 5, 6, 5, 6, 2, 7, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0
]
flag =
for i in range(0,len(data)-1,2):
a = data[i]
b = data[i 1]
flag = chr(ab * 16)
print(flag)
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 16 条评论) |
本站网友 厨房家居 | 2分钟前 发表 |
116 | |
本站网友 北京和美医院 | 6分钟前 发表 |
0xD1 | |
本站网友 配货公司 | 16分钟前 发表 |
对于加密和解密中应用的密钥流的产生 | |
本站网友 牢不可破的联盟 | 4分钟前 发表 |
88 | |
本站网友 4月1 | 8分钟前 发表 |
0xCB | |
本站网友 结石的症状 | 3分钟前 发表 |
212 | |
本站网友 部分 | 25分钟前 发表 |
198 | |
本站网友 好伦哥自助餐 | 25分钟前 发表 |
76 | |
本站网友 军海治疗羊角风医院 | 9分钟前 发表 |
0xEF | |
本站网友 放血疗法治疗皮肤病 | 13分钟前 发表 |
6 | |
本站网友 新安租房网 | 29分钟前 发表 |
4 | |
本站网友 上海牙齿整形 | 1分钟前 发表 |
16 | |
本站网友 人均收入排名 | 29分钟前 发表 |
1 | |
本站网友 被捆绑 | 1分钟前 发表 |
0 | |
本站网友 姜大明 | 6分钟前 发表 |
15 |