H&NCTF
好难好难好难
hnwanna
一开始以为是il2cpp打包的,但是找不到关键文件
应该是mono打包的
找到该文件,拖进dnspy
这里找到flag文本
一开始以为直接修改if判断条件让游戏自己跳flag就行
但是什么默认值乌拉乌拉的,改不了,那就静态分析吧
str就是flag,可以发现是经过了a函数
凯撒加密,回到原函数,input和shift(就是5)都有了
加上前缀就好了
I_LOVE_SWDD
sub_41127B是反调试函数,可以发现sub_411186函数进行了输入加密
点进来
发现smc加密,在417001下断点,动调
先瞎打一个
会在断点停下
对hello函数进行重写(p),f5反编译
可以发现偏移量为10的凯撒加密
最喜欢的逆向题
纯签到题
字符串发现一堆flag
挨个交一下发现flag
H&NCTF{Do_Y0u_like_F5_1n_Rev}
这次比赛就搞出来三个re,哎还是菜,剩下的就等wp喽
buu
[FlareOn1]Bob Doge
下载,dnspy64位打开
f9下断点,运行
text就是flag
[MRCTF2020]PixelShooter
下载是dnspy文件
jeb分析一下,没有找到有用的东西
后缀改成zip解压
第一个文件拖进dnspy
然后将apk装在模拟器上,运行一下
是个游戏,在dnspy搜索关键字
直接就给flag
[WUSTCTF2020]Cr0ssfun
下载,64位,拖进ida
点进check函数
依次点入,可以找全a1数组
#include<iostream>
using namespace std;
int main()
{
int a1[33];
a1[10] = 112;
a1[13] = 64;
a1[3] = 102;
a1[26] = 114;
a1[20] = 101;
a1[7] = 48;
a1[16] = 95;
a1[11] = 112;
a1[23] = 101;
a1[30] = 117;
a1[0] = 119;
a1[6] = 50;
a1[22] = 115;
a1[31] = 110;
a1[12] = 95;
a1[15] = 100;
a1[8] = 123;
a1[18] = 51;
a1[28] = 95;
a1[21] = 114;
a1[2] = 116;
a1[9] = 99;
a1[32] = 125;
a1[19] = 118;
a1[5] = 48;
a1[14] = 110;
a1[4] = 50;
a1[17] = 114;
a1[29] = 102;
a1[17] = 114;
a1[24] = 95;
a1[1] = 99;
a1[25] = 64;
a1[27] = 101;
for (int i = 0; i < 33; i++)
{
cout<< static_cast<char>(a1[i]);
}
}
写代码排序输出一下
[ACTF新生赛2020]Universe_final_answer
找到关键函数
from sympy import symbols, Eq, solve
# 定义未知数
v1, v2, v3, v4, v5, v6, v7, v8, v9, v11 = symbols('v1 v2 v3 v4 v5 v6 v7 v8 v9 v11')
# 定义方程组
eq1 = Eq(-85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3, 12613)
eq2 = Eq(30 * v11 + -70 * v9 + -122 * v6 + -81 * v7 + -66 * v5 + -115 * v4 + -41 * v3 + -86 * v1 - 15 * v2 - 30 * v8, -54400)
eq3 = Eq(-103 * v11 + 120 * v8 + 108 * v7 + 48 * v4 + -89 * v3 + 78 * v1 - 41 * v2 + 31 * v5 - (v6 ** 6) - 120 * v9, -10283)
eq4 = Eq(71 * v6 + (v7 ** 7) + 99 * v5 + -111 * v3 + 85 * v1 + 79 * v2 - 30 * v4 - 119 * v8 + 48 * v9 - 16 * v11, 22855)
eq5 = Eq(5 * v11 + 23 * v9 + 122 * v8 + -19 * v6 + 99 * v7 + -117 * v5 + -69 * v3 + 22 * v1 - 98 * v2 + 10 * v4, -2944)
eq6 = Eq(-54 * v11 + -23 * v8 + -82 * v3 + -85 * v2 + 124 * v1 - 11 * v4 - 8 * v5 - 60 * v7 + 95 * v6 + 100 * v9, -2222)
eq7 = Eq(-83 * v11 + -111 * v7 + -57 * v2 + 41 * v1 + 73 * v3 - 18 * v4 + 26 * v5 + 16 * v6 + 77 * v8 - 63 * v9, -13258)
eq8 = Eq(81 * v11 + -48 * v9 + 66 * v8 + -104 * v6 + -121 * v7 + 95 * v5 + 85 * v4 + 60 * v3 + -85 * v2 + 80 * v1, -1559)
eq9 = Eq(101 * v11 + -85 * v9 + 7 * v6 + 117 * v7 + -83 * v5 + -101 * v4 + 90 * v3 + -28 * v1 + 18 * v2 - v8, 6308)
eq10 = Eq(99 * v11 + -28 * v9 + 5 * v8 + 93 * v6 + -18 * v7 + -127 * v5 + 6 * v4 + -9 * v3 + -93 * v1 + 58 * v2, 1697)
# 求解方程组
solution = solve((eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10), (v1, v2, v3, v4, v5, v6, v7, v8, v9, v11))
if solution:
# 输出各未知数的值
print(solution)
else:
print("方程组无解或无法求解。")
作为字符串输 出 后得到 F0uRTy_7w@ flag{F0uRTy_7w@}
[SCTF2019]babyre
下载
ida64位
没找到main函数,字符串碰碰运气
交叉引用
发现花指令,nop掉但是还是不行
发现不只一处花,都nop掉
全选函数按p重写函数
f5反编译出主函数
第一部分是迷宫
路径是ddwwxxssxaxwwaasasyywwdd
第二部分点进去发现base64加密
根据第三部分的代码逆向出结果
def ROR4(x, y):
return ((x << (32 - y)) | (x >> y)) & 0xffffffff
def ROL4(x, y):
return ((x >> (32 - y)) | (x << y)) & 0xffffffff
def sub_1464(a1):
v3 = [
0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7,
0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A,
0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95,
0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6,
0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,
0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8,
0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B,
0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2,
0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87,
0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,
0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E,
0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5,
0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55,
0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3,
0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,
0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F,
0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F,
0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F,
0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8,
0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,
0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0,
0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E,
0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20,
0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48,
0xC6, 0xBA, 0xB1, 0xA3, 0x50, 0x33, 0xAA, 0x56,
0x97, 0x91, 0x7D, 0x67, 0xDC, 0x22, 0x70, 0xB2,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
v2 = (v3[(a1 >> 8) & 0xff] << 16) | v3[a1 & 0xff] | (v3[(a1 >> 24) & 0xff] << 8) | (v3[(a1 >> 16) & 0xff] << 24)
return ROL4(v2, 12) ^ ROL4(v2, 8) ^ ROR4(v2, 2) ^ ROR4(v2, 6)
v10 = [0]*30
v10[26] = 0xBE040680
v10[27] = 0xC5AF7647
v10[28] = 0x9FCC401F
v10[29] = 0xD8BF92EF
n = 25
while n >= 0:
v10[n] = v10[n + 4] ^ sub_1464(v10[n + 1] ^ v10[n + 2] ^ v10[n + 3])
n -= 1
result = ""
for i in range(4):
result += chr(v10[i] & 0xff)
result += chr((v10[i] >> 8) & 0xff)
result += chr((v10[i] >> 16) & 0xff)
result += chr((v10[i] >> 24) & 0xff)
print(result)
sctf{ddwwxxssxaxwwaasasyywwdd-c2N0Zl85MTAy(fl4g_is_s0_ug1y!)}
[GUET-CTF2019]encrypt
找到一个rc4加密
一开始当自定义加密写的,看wp是魔改的base64
gpt写的代码,运行一下
from base64 import *
import binascii
from Crypto.Util.number import *
duibi="Z`TzzTrD|fQP[_VVL|yneURyUmFklVJgLasJroZpHRxIUlH\\vZE="
# for i in range(len(duibi)-1):
# print(hex(ord(duibi[i])-61),end=",")#得到shuru
shuru=[0x1d,0x23,0x17,0x3d,0x3d,0x17,0x35,0x7,0x3f,0x29,0x14,0x13,0x1e,0x22,0x19,0x19,0xf,0x3f,0x3c,0x31,0x28,0x18,0x15,0x3c,0x18,0x30,0x9,0x2e,0x2f,0x19,0xd,0x2a,0xf,0x24,0x36,0xd,0x35,0x32,0x1d,0x33,0xb,0x15,0x3b,0xc,0x18,0x2f,0xb,0x1f,0x39,0x1d,0x8,0]
def four_to_three(a1,a2,a3,a4):
return (a1<<18)|(a2<<12)|(a3<<6)|a4
for i in range(0,len(shuru),4):
temp=four_to_three(shuru[i],shuru[i+1],shuru[i+2],shuru[i+3])
a1=temp>>16
a2=(temp>>8)&0xff
a3=(temp)&0xff
print(hex(a1)[2:].rjust(2,'0'),end="")
print(hex(a2)[2:].rjust(2,'0'), end="")
print(hex(a3)[2:].rjust(2,'0'), end="")
data1="7635fdf57d47fe95137a26593fff31a1857c63026ebd936a3e4d8dd727732d5ecc62f2dfe5d2"
def rc4_crypt(text,key):
textlen=len(text)
keylen=len(key)
ciper=[]
count=0
s=list(range(256))
for i in range(256):
count=(count+s[i]+key[i%keylen])%256
s[i],s[count]=s[count],s[i]
i=0
j=0
for m in range(textlen):
i=(i+1)%256
j=(j+s[i])%256
s[i],s[j]=s[j],s[i]
k=s[(s[i]+s[j])%256]
ciper.append(k^text[m])
ciper_text=''.join("%02x"%i for i in ciper)
return ciper_text.upper()
if __name__ == "__main__":
data = '7635fdf57d47fe95137a26593fff31a1857c63026ebd936a3e4d8dd727732d5ecc62f2dfe5d2'
key = '1020303020201040'
print()
print("rc4 result:", rc4_crypt(binascii.a2b_hex(data), binascii.a2b_hex(key.upper())))
print(long_to_bytes(0x666C61677B65313061646333393439626135396162626535366530353766323066383833657D))
[ACTF新生赛2020]fungame
一个异或 仔细观察发现是栈溢出,这个函数先把flag复制到了只能容纳12个字节的Destination,必定发生溢出,而第二次则复制到了x
一个base64加密
import base64
y1=[0x23,0x61,0x3E,0x69,0x54,0x41,0x18,0x4D,0x6E,0x3B,0x65,0x53,0x30,0x79,0x45,0x5B]
y2=[0x71,0x04,0x61,0x58,0x27,0x1E,0x4B,0x22,0x5E,0x64,0x3,0x26,0x5E,0x17,0x3C,0x7A]
flag='flag{'
for i in range(len(y1)):
flag+=chr(y1[i]^y2[i])
flag+=chr(0x40)+chr(0x23)+chr(0x3D)+str(base64.b64decode('YTFzMF9wV24='),encoding = "utf-8") #bytes转str
print(flag+'}')
运行一下得到flag flag{Re_1s_So0_funny!@#=a1s0_pWn}
[WUSTCTF2020]funnyre
f5不了,字符串也没有什么有用的,在这里找到main函数(真坏啊)
点进
去除四处花指令后反编译
得到一个很长的函数 最后与已知的数组比较结果
这些变换都是限制在BYTE范围内的
也就是说 这些变换都可以等价为0~256的某个数的一次变换
所以两种变换(取反也可以等价为xor)分别枚举0~256的一次变换即可
dt = [0xd9, 0x2c, 0x27, 0xd6, 0xd8, 0x2a, 0xda, 0x2d, 0xd7, 0x2c, 0xdc, 0xe1, 0xdb, 0x2c, 0xd9, 0xdd, 0x27, 0x2d, 0x2a, 0xdc, 0xdb, 0x2c, 0xe1, 0x29, 0xda, 0xda, 0x2c, 0xda, 0x2a, 0xd9, 0x29, 0x2a]
def move(xx, kk):
return [(x+kk) & 0xFF for x in xx]
def xor(xx, kk):
return [x ^ kk for x in xx]
def check(xx): # 16进制
for x in xx:
if x < ord('0') or (x > ord('9') and x < ord('a')) or x > ord('f'):
return False
return True
if __name__ == '__main__':
for k1 in range(0x100):
tt = move(dt, k1)
for k2 in range(0x100):
tt2 = xor(tt, k2)
if check(tt2):
print(bytes(tt2))
print(k1, k2)
flag{1dc20f6e3d497d15cef47d9a66d6f1af}
[CISCN2018]2ex
分析函数可知是base64变表加密
字符串找到新表
[watevrCTF 2019]Timeout
下载拖进ida
无代码
搜一下可以改后缀为elf,拖进ida
翻一下找到flag
[UTCTF2020]babymips
拖进ida
判断前五位是不是flag{
进行了移位加密
加密后的数据,写爆破脚本
flag{ReA11y_4_B@89_mlp5_4_XmAn_}
[BJDCTF2020]BJD hamburger competition
下载,打开
这个拖进dnspy
通过字符串找到关键函数
将这个Sha1加密的字符串解密
然后使用MD5加密
flag{B8C37E33DEFDE51CF91E}
[ACTF新生赛2020]Oruga
迷宫题,主要流程在这个函数
jmew控制左下右上
提取出地图
脚本解除路径
flag{MEWEMEWJMEWJM}
[FlareOn4]IgniteMe
下载,查看代码
有一个getstdhandle函数
GetStdHandle()函数:
检索指定标准设备的句柄(标准输入、标准输出或标准错误)
GetStdHandle 返回的句柄可供需要在控制台中进行读取或写入的应用程序使用。 创建控制台时,标准输入句柄是控制台输入缓冲区的句柄,而标准输出和标准错误句柄则是控制台的活动屏幕缓冲区的句柄。 这些句柄可供 ReadFile 和 WriteFile 函数使用,也可供访问控制台输入缓冲区或屏幕缓冲区的任何控制台函数(例如 ReadConsoleInput、WriteConsole GetConsoleScreenBufferInfo 函数)使用。可以为下面的输入输出做准备
这里有一个_rol4_函数
_ROL4_函数 的功能是循环左移,位移时最高位不舍弃,将最高位挪回最低位 比如二进制数据 10000,循环左移2位后得到00010
两个参数,第一个参数是要进行左移的数据,第二个是要进行移位的长度
同时我们也可以类比一下ROR4函数,就是循环右移函数,使用和上面一样
对于这个题目,就是将-2147024896循环左移4位,然后再右移一位,我们可以看看他的值
首先这个值是0x80070000
接着循环左移4位:0x700008 (因为是16进制,移动一位就是移动二进制的四位)
最后右移一位:0x380004(看大佬的wp才搞懂的)
脚本解密出结果
[FlareOn5]Minesweeper Championship Registration
jar文件,拖进jadx
直接发现flag
GoldenTicket2018@flare-on.com
[GDOUCTF 2023]Check_Your_Luck
下载cpp,vs打开
sympy脚本秒了
from sympy.solvers import solve
from sympy import Symbol
# 定义变量
v = Symbol('v')
w = Symbol('w')
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
# 定义方程组
eq1 = v * 23 + w * (-32) + x * 98 + y * 55 + z * 90 - 333322
eq2 = v * 123 + w * (-322) + x * 68 + y * 67 + z * 32 - 707724
eq3 = v * 266 + w * (-34) + x * 43 + y * 8 + z * 32 - 1272529
eq4 = v * 343 + w * (-352) + x * 58 + y * 65 + z * 5 - 1672457
eq5 = v * 231 + w * (-321) + x * 938 + y * 555 + z * 970 - 3372367
# 求解方程组
sol = solve((eq1, eq2, eq3, eq4, eq5), (v, w, x, y, z))
# 输出结果
print(sol)
[NSSRound#3 Team]jump_by_jump_revenge
发现花指令,nop掉
main_0函数按p重写
根据逻辑写出脚本
NSSCTF{Jump_b9_jump!_r3V3n9e}
[GDOUCTF 2023]Tea
根据名字判断是tea加密
双击sub_140011339(v7)跟进,然后跟进sub_1400117D0(a1)函数,可知v7为key,且被更改为{2233,4455,6677,8899},双击 sub_1400112B7(v8, v7),跟进sub_140011900(a1, a2)函数,
def xtea_decrypt(data,key):
for j in range(8,-1,-1):
i = 0
delta = 256256256
sum = delta * (32 + j)
n = j + 1
while i <= 32:
i += 1
data[n] = (data[n] - (((key[(sum >> 11) & 3]) + sum) ^ (((data[j] << 4) ^ (data[j] >> 5)) + data[j]))) & 0xffffffff
data[j] = (data[j] - (((key[sum & 3] + sum) ^ ((data[n] << 4) ^ (data[n] >> 5)) + data[n]) ^ sum)) & 0xffffffff
sum -= delta
return data
v8 = [0x1A800BDA,0xF7A6219B,0x491811D8,0xF2013328,0x156C365B,0x3C6EAAD8,0x84D4BF28,0xF11A7EE7,0x3313B252,0xDD9FE279]
key = [2233,4455,6677,8899]
flag = xtea_decrypt(v8,key)
for i in range(10):
for j in range(3,-1,-1):
print(chr((flag[i] >> (j * 8)) & 0xFF), end='')
HZCTF{hzCtf_94_re666fingcry5641q q}
[MoeCTF 2022]Hex
拖进hxd,向下翻找找到flag
[HNCTF 2022 Week1]Little Endian
异或后得到的十六进制,需要逆序一下;
enc = [0x51670536, 0x5E4F102C, 0x7E402211, 0x7C71094B, 0x7C553F1C, 0x6F5A3816,]
key = [(enc[i] ^ 0x12345678) for i in range(len(enc))]
flag = []
for i in range(len(key)):
key[i] = hex(key[i])[2:][::-1]
key[i] = ''.join(key[i][j:j+2][::-1]for j in range(0,8,2))
for x in key:
hex_num = [x[i:i+2]for i in range(0,8,2)]
flagn = [chr(int(xx,16))for xx in hex_num]
flag.append(''.join(flagn))
print(''.join(flag))
NSSCTF{Littl3_Endiannnn}