文章目录
- @[toc]
- shiftjmp
- 点击就送的逆向题
- 幸运数字
- flower-or-tea
- 小黄鸭
- mySelf
- easymath
- 听说cpp很难?
- 砍树
- 浪漫至死不渝
- 是男人就来扎针
- ezandroid
文章目录
- @[toc]
- shiftjmp
- 点击就送的逆向题
- 幸运数字
- flower-or-tea
- 小黄鸭
- mySelf
- easymath
- 听说cpp很难?
- 砍树
- 浪漫至死不渝
- 是男人就来扎针
- ezandroid
shiftjmp
64bit的ELF文件,IDA打开
考察花指令去除、将E9 nop掉
EXP:
enc = [ 0x53, 0x58, 0x41, 0x78, 0x53, 0x36, 0x6A, 0x64, 0x38, 0x64,
0x6F, 0x54, 0x78, 0x42, 0x51, 0x7B, 0x78, 0x22, 0x4D, 0x61,
0x27, 0x63, 0x73, 0x45, 0x2D, 0x7C, 0x45, 0x6C, 0x2C, 0x6F,
0x2F, 0x7B, 0x5E, 0x5C]
flag = []
for i in range(34):
flag.append(chr(enc[i]^i))
print(''.join(flag))
# SYC{W3lc0me_tO_th3_r3veR5e_w0r1d~}
点击就送的逆向题
64bit的ELF文件。
做了一个简单的加法,逆向一下减去就好。
EXP:
enc = 'Z`J[X^LMNO`PPJPVQRSIUTJ]IMNOZKMM'
flag = []
for i in range(len(enc)):
flag.append(chr(ord(enc[i])-7))
print(''.join(flag))
# SYCTQWEFGHYIICIOJKLBNMCVBFGHSDFF
幸运数字
本来想试试result可不可以解出幸运数字,后来发现可以用已知字符来解密。
for i in range(999):
if 0xD^(i%0xD3) == 0x53:
print(i)
#94 305 516 727 938
用idapython提取数据。
addr = 0x40159C
enc = []
for i in range(1,42,1):
enc.append(idc.get_db_byte(addr+4*i))
print(enc)
EXP:
enc = [13, 7, 29, 37, 29, 110, 48, 57, 44, 63, 42, 43, 50, 63, 42, 55, 110, 48, 48, 48, 48, 45, 1, 7, 49, 43, 1, 57, 31, 59, 45, 45, 27, 58, 1, 12, 111, 57, 54, 42, 35]
flag = []
for i in range(41):
flag.append(chr(enc[i] ^ (94 % 0xD3)))
print(''.join(flag))
# SYC{C0ngratulati0nnnns_You_gAessEd_R1ght}
flower-or-tea
32bit C++文件
去除花指令
全都是简单的jnz和jz互补跳转,将E8或者E9全部改为90就好,下面的有些数据转换成代码也是一样的操作。
之后记得把黄色的部分修复一下。
之后得到正确的代码,一些数据和一些已知字符串。
sub点进去
XTEA加密,撸个解密脚本出来
先写个idapython提取下数据,
addr = 0x40125E
enc = []
for i in range(1,26,1):
enc.append(idc.get_wide_dword(addr+7*i))
addr += 3
addr = 0x401358
for i in range(1,14,1):
enc.append(idc.get_wide_dword(addr+4*i))
addr += 3
print(enc)
EXP:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void decrypt (uint32_t* v,uint32_t* k) {
uint32_t v0=v[0], v1=v[1], i;
uint32_t delta=0x31415927;
uint32_t sum = delta*54;
for (i=0; i<54; i++) {
sum -= delta;
v0 -= (((v1 * 16) ^ (v1 >> 5)) + v1) ^ (sum + k[(sum & 3)]);
v1 -= (((v0 * 16) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11 ) & 3])^sum;
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t enflag[] = {2600027723, 3289888926, 2987894547, 3376130536, 2499011662, 3050056373, 1146217516, 2055874714, 1405669384, 1846639433, 2617235348, 1593781753, 401024305, 3753744761, 2407996218, 1944634796, 2995155110, 1526113129, 754440740, 880502447, 3116911968, 2434699567, 3176804251, 3415634746, 3315165374, 2684359657, 3241103012, 3733338640, 2697254292, 1132501052, 2117039688, 3847085193, 1059563152, 3045929369, 1615521047, 2626697604, 4108338305, 1022684671};
uint32_t key[4] = {32,27,39,44};
for(int i=0;i<38;i+=2)
{
uint32_t temp[2];
temp[0] = enflag[i];
temp[1] = enflag[i+1];
decrypt(temp,key);
//printf("%X%X",temp[0],temp[1]);
printf("%c %c ",temp[0],temp[1]);
//printf("%c%c%c%c%c%c%c%c",*((char*)&temp[0]+0),*((char*)&temp[0]+1),*((char*)&temp[0]+2),*((char*)&temp[0]+3),*((char*)&temp[1]+0),*((char*)&temp[1]+1),*((char*)&temp[1]+2),*((char*)&temp[1]+3));
}
return 0;
}
//S } Y ? C ? { A D e 0 t _ _ Y r o 3 v w _ o 1 l i F k _ e k _ n T i o R _ d
因为先前加密的时候用的是第一个和最后一个加密,所以解密的flag自己再手动调整下。
小黄鸭
pyinstaller编译的,考察py逆向,用pyinstxtractor解包
找到1.pyc,之后使用uncompyle6反编译
if a[i].isalpha():
检查当前字符是否是字母字符,如果是的话就对它进行一个ROT13的加密(凯撒加密)之后进行加法处理;
写个EXP(直接复制原代码的加密逻辑,改一下就好)
a = '~h|p4gs`gJdN`thPwR`jDn`te1w`2|RNH'
b = []
for i in range(len(a)):
if a[i].isalpha():
c = a[i]
c = chr(ord(c) + 13 - 26 if ord(c) + 13 > (90 if c <= 'Z' else 122) else ord(c) + 13)
b.append(chr(ord(c) - 2))
else:
b.append(chr(ord(a[i]) - 1))
b = b[::-1]
print(''.join(b))
# S?C{1_h0pe__Ou_ChAse_?oUr_dr3a{s}
记得有个逆序。
之后再根据源代码中的提示以及一点猜测还原flag。这里因为环境关闭了没办法复现了。
mySelf
看到VirtualProtect,这个函数在windows中有修改内存读写权限的功能,它对sub_4013B0地址起的读写权限进行了修改。
直接动态调试,单步进入函数内。将起始处一直到第一个retn的汇编全部U掉,再转换成代码,反编译
一个魔改的TEA加密,不需要key
EXP:
#include <stdio.h>
#include <stdint.h> // 使用uint32_t数据类型需要包含此头文件
#include <string.h>
#include<iostream>
using namespace std;
void decrypt(unsigned int *v){
unsigned int v0 = v[0],v1 = v[1], sum = 0, delta = 0x61C88647;
sum = -(delta * 32);
for (size_t i = 0; i < 32; i++){
v1 -= ((v0>>5)+4) ^ (16*v0+3)^(sum+v0);
v0 -= ((v1>>5)+2) ^ (16*v1+2)^(sum+v1);
sum += delta;
}
v[0] = v0;
v[1] = v1;
}
unsigned char a[41] = { 0xF0, 0xF9, 0xBD, 0xBD, 0xC4, 0x94, 0x61, 0xE2, 0x25, 0x91,
0x79, 0x80, 0x19, 0xC2, 0x0F, 0x1F, 0x15, 0x18, 0x6A, 0xEB,
0xC5, 0x72, 0xF5, 0x84, 0x85, 0x3A, 0xCC, 0x40, 0xBB, 0x2A,
0xA3, 0xD2};
//unsigned int key[] = {5,20,13,14};
signed main(){
unsigned int *t = (unsigned int *)a;
for (int i = 0; i < 7; i += 2){
decrypt(t+i);
}
for (int i = 0; i < 8; i++){
printf("%c%c%c%c", *((char *)&t[i] + 0), *((char *)&t[i] + 1), *((char *)&t[i] + 2), *((char *)&t[i] + 3));
}
}
// SYC{H0w_7o_R@te_YOurs31f_iNtRo?}
easymath
64bit文件
用Z3约束求解,下面的for循环照抄,最后俩个if作为约束条件。
上面就是check检查flag是否是table里的内容,再得到flag在table的索引,根据索引在number中找出对应值。
EXP:
from z3 import *
s = Solver()
x = [BitVec(f'x[{i}]', 8) for i in range(25)]
matrix = [18, 29, 16, 19, 27, 8, 31, 8, 23, 30, 29, 3, 28, 10, 21, 18, 29, 8, 16, 28, 11, 30, 7, 20, 7]
v7 = [0] * 25
for i in range(5):
for j in range(5):
for k in range(5):
v7[5 * i + j] = (v7[5 * i + j] + x[5 * i + k] * matrix[5 * k + j]) & 0x1F
if i == j:
s.add(v7[5 * i + j] == 1)
if i != j:
s.add(v7[5 * i + j] == 0)
if s.check() == sat:
m = s.model()
number = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19, 22, 26, 27, 28, 29, 31, 32, 50, 51, 52, 53, 54, 55, 56]
for i in range(25):
for j in range(len(number)):
if m[x[i]] == number[j]:
print('01234_asdzxcpoityumnbAOZWXGMY'[j],end='')
# xtd4co_ymiunbbx3Aypsmbzii
听说cpp很难?
cpp逆向,64bit文件。
密文数据。
动态调试发现,在94行做了+10的操作,后面text_47;跟进
化简后就是,先异或10再减去10;逆向一下:
EXP:
enc = [77, 95, 61, -123, 55, 104, 115, 87, 39, 104, 81, 89, 127, 38, 107, 89, 115, 87, 85, 91, 89, 111, 106, 89, 39, 87, 114, 87, 79, 87, 120, 120, -125]
print(''.join(chr(0xff&(((x+10)^10)-10))for x in enc))
# SYC{Anma1nG_y0u_maKe_it_1alaIa~~}
砍树
native层逆向
jdax打开,看Mainactivity
这里用了一个I0o0I函数,还有密文Sycloverforerver
用apktool解包,去逆so里的I0o0I函数,
加密部分
EXP:
key = 'Sycloverforerver'
enc = [0x00, 0x20, 0x20, 0x17, 0x1B, 0x36, 0x0E, 0x36, 0x26, 0x17,
0x04, 0x2A, 0x29, 0x07, 0x26, 0x15, 0x52, 0x33, 0x2D, 0x0F,
0x3A, 0x27, 0x11, 0x06, 0x33, 0x07, 0x46, 0x17, 0x3D, 0x0A,
0x3C, 0x38, 0x2E, 0x22, 0x18]
flag = []
for i in range(len(enc)):
flag.append(chr(enc[i] ^ ord(key[i%7])))
print(''.join(flag))
# SYC{t@ke_thE_bul1_By_the_h0rns_TAT}
浪漫至死不渝
逆index.js ; vscode打开就好。
对 ‘53X211WH04N’ 进行三次的栅栏密码。
得到5201314wxhn
之后就是线性代换:
array在上面。
EXP:
enc = [125, 130, 131, 122, 117, 110, 123, 125, 130, 131, 122, 117, 110, 123, 99, 99, 99, 99]
enc2 = '5201314wxhn'
flag = []
for i in range(len(enc)):
if i < 14:
flag.append(chr((enc[i] - 10) ^ ord(enc2[i % 7])))
else:
flag.append(chr((enc[i] - 99) ^ ord(enc2[i - 7])))
print(''.join(flag))
# FJIAXUEFJIAXUEwxhn
是男人就来扎针
C# unity游戏逆向,用dnspy打开
运行游戏的时候要用dnspy64,所以这里用dnspy64打开。看Gamemanager:
主要逻辑
每扎一次针异或一次,所以这里不能通过修改分数来得到flag(每次结果都不同)。
本来也想通过例如让针碰撞无效的思路来破解,没有找到在哪里,直接爆破吧。
EXP:
from hashlib import *
magicc = [75,
109,
102,
63,
107,
112,
63,
108,
124,
112,
109,
122,
63,
43,
47,
63,
111,
112,
118,
113,
107,
108,
62]
magic = [124,
90,
81,
8,
92,
71,
8,
90,
77,
73,
75,
64,
8,
25,
24,
24,
8,
88,
71,
65,
70,
92,
91,
9]
for i in range(101):
decode1 = []
decode2 = []
for j in range(len(magic)):
decode1.append(chr((magic[j] ^ i)))
for j in range(len(magicc)):
decode2.append(chr((magicc[j] ^ i)))
print(i, "".join(decode1), ''.join(decode2),
md5(''.join(decode2).encode()).hexdigest())
ezandroid
apk文件,用jadx打开;
魔改的TEA,第一次加密的v1,继续作为第二组的v0加密。
分析代码,
作了一个点击后的处理方法,如果字符串长度超过24就清空,为0或者不足24就自动往后面补充"X",。这个字符串对象名叫 sb。
将sb,按照奇偶位分成了sb2和sb3。接着,对sb4,也就是sb2做了一个TEA加密。
密文和key
接着看,MainActivity2
作了一个异或,使用了俩个对象,“ad@#E!@a123"和"eCAS213@!@3”。在MainActivity中可以看到
sb5,就是 sb4 即第二部分字符串,bArr就是第一部分的字符串经过加密后的字符串。
所以这里就用俩个已知数组异或可以得到sb5。
EXP:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void decrypt(int *v, int *k)
{
int v0 = v[0], v1 = v[2], v2 = v[1], sum = 0x9E3779B9 * 64, i;
/* set up */
int delta = 0x9E3779B9;
/* a key schedule constant */
int k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
/* cache key */
for (i = 0; i < 32; i++)
{ /* basic cycle start */
v1 -= (((v2 << 4) + k2) ^ (v2 + sum)) ^ ((v2 >> 5) + k3);
v2 -= (((v1 << 4) + k0) ^ (v1 + sum)) ^ ((v1 >> 5) + k1);
sum -= delta;
}
for (i = 0; i < 32; i++)
{ /* basic cycle start */
v1 -= (((v0 << 4) + k2) ^ (v0 + sum)) ^ ((v0 >> 5) + k3);
v0 -= (((v1 << 4) + k0) ^ (v1 + sum)) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
int main()
{
char encode1[12] = {-91, -8, -110, -55, -49, 75, 115, 13, -76,
-113, 102, 80};
char encode2[12] = {-107, -106, -95, -115, -119, 127, 26, 121, -62, -20, 86, 9};
int key[4] = {2023708229, -158607964, -2120859654, 1167043672};
char temp;
for (int j = 0; j < 12; j++)
{
encode2[j] = encode1[j] ^ encode2[j];
}
for (int i = 0; i < 3; i++)
{
temp = encode1[4 * i];
encode1[4 * i] = encode1[4 * i + 3];
encode1[4 * i + 3] = temp;
temp = encode1[4 * i + 1];
encode1[4 * i + 1] = encode1[4 * i + 2];
encode1[4 * i + 2] = temp;
}
int *flag1 = (int *)encode1;
decrypt(flag1, key);
for (int i = 0; i < 3; i++)
{
temp = encode1[4 * i];
encode1[4 * i] = encode1[4 * i + 3];
encode1[4 * i + 3] = temp;
temp = encode1[4 * i + 1];
encode1[4 * i + 1] = encode1[4 * i + 2];
encode1[4 * i + 2] = temp;
}
for (int i = 0; i < 12; i++)
{
putchar(encode1[i]);
putchar(encode2[i]);
}
system("pause");
return 0;
}
// T00nV3tD3F34Tint0vict0rY