2024newstar

Simple_encryption

Week1 - Reverse 逆向工程
简单
出题人:tgrddf55
一眼秒的算法

alt text

  • 写脚本

alt text

  • 唉放弃python非得用c
#include <stdio.h>

unsigned char buffer[] = { 0x47,0x95,0x34,0x48,0xa4,0x1c,0x35,0x88,0x64,0x16,0x88,0x07,0x14,0x6a,0x39,0x12,0xa2,0x0a,0x37,0x5c,0x07,0x5a,0x56,0x60,0x12,0x76,0x25,0x12,0x8e,0x28 };
int main() {
int len = 30;
for (int i = 0; i < len; i++) {
if (i % 3 == 0) {
buffer[i] += 0x1f;
}
if (i % 3 == 1) {
buffer[i] -= 0x29;
}
if (i % 3 == 2) {
buffer[i] ^= 0x55;
}
}
printf("%s", buffer);

return 0;
}
// flag{IT_15_R3Al1y_V3Ry-51Mp1e}

base64

Week1 - Reverse 逆向工程
简单
出题人:0xA1pha
仍然是 base64

alt text

begin

Week1 - Reverse 逆向工程
签到
出题人:tgrddf55
什么是 IDA?

flag_part1      db 'flag{Mak3_aN_',0       ;要uddda
this is flag part2: 3Ff0rt_tO_5eArcH_ ,You can press
int F0r_th3_f14g_C0Rpse()
{
printf_0("the function name is flag part3,Don't forget to add a '}' at the end");
return flag_part2();
}

flag{Mak3_aN_3Ff0rt_tO_5eArcH_F0r_th3_f14g_C0Rpse}

ezandroidstudy

Week1 - Reverse 逆向工程
简单
出题人:PangBai
这是什么?猫猫虫?

ez_debug

Week1 - Reverse 逆向工程
简单
出题人:kw17
动态调试(可能 xdbg 会更简单哦)

alt text

0000000000401D11 | 48:8D95 40010000 | lea rdx,qword ptr ss:[rbp+140] | [rbp+140]:“flag{y0u_ar3_g0od_@_Debu9}”

ezencrypt

Week2 - Reverse 逆向工程
中等
出题人:PangBai
有一位魔女坐着扫帚飞在空中,灰色头发在风中飘逸,这位像洋娃娃一般漂亮又可爱,连夏天的当空烈日见了都会放出更炙热光芒的少女,究竟是谁呢,没错就是我。

之前做过一遍,点击
alt text
alt text
alt text

  • AES/ECB/PKCS5Padding key=IamEzEncryptGame
  • base64
  • doEncCheck
  • xor
  • rc4

alt text

Dirty_flowers

Week2 - Reverse 逆向工程
简单
出题人:tgrddf55
IDA 的 F5 怎么失效了

alt text

  • 这里真是乱七八糟,失败请尝试选择函数范围再ucp f5
  • nop(字节0x90)
  • 函数名u p f5
  • 注意这里的函数名是最上边的函数名
  • ai
if ( &v11[strlen(&v10)] - v11 == 36 )
  • 修一下

alt text

  • 这里很诡异的结果很诡异的修法不完全解决,尝试n次最好还是选择函数范围再ucp f5

alt text

  • 官方脚本
# exp.py
lis = [0x02, 0x05, 0x13, 0x13, 0x02, 0x1e, 0x53, 0x1f, 0x5c, 0x1a, 0x27, 0x43, 0x1d, 0x36, 0x43,
0x07, 0x26, 0x2d, 0x55, 0x0d, 0x03, 0x1b, 0x1c, 0x2d, 0x02, 0x1c, 0x1c, 0x30, 0x38, 0x32,
0x55, 0x02, 0x1b, 0x16, 0x54, 0x0f]
str = "dirty_flower"
flag = ""
for i in range(len(lis)):
lis[i] ^= ord(str[i % len(str)])
flag += chr(lis[i])
print(flag)
# flag{A5s3mB1y_1s_r3ally_funDAm3nta1}

alt text

UPX

Week2 - Reverse 逆向工程
简单
出题人:nuthecz
你知道 upx 吗?

alt text
alt text
alt text

  • 官方脚本
#include <stdio.h>
#include <string.h>

unsigned char sbox[256] = {0};
const unsigned char* key = (const unsigned char*)"NewStar";
unsigned char data[22] = {-60, 96, -81, -71, -29, -1, 46, -101, -11, 16, 86,
81, 110, -18, 95, 125, 125, 110, 43, -100, 117, -75};

void swap(unsigned char* a, unsigned char* b) {
unsigned char tmp = *a;
*a = *b;
*b = tmp;
}

void init_sbox(const unsigned char key[]) {
for (unsigned int i = 0; i < 256; i++) sbox[i] = i;
unsigned int keyLen = strlen((const char*)key);
unsigned char Ttable[256] = {0};
for (int i = 0; i < 256; i++) Ttable[i] = key[i % keyLen];
for (int j = 0, i = 0; i < 256; i++) {
j = (j + sbox[i] + Ttable[i]) % 256;
swap(&sbox[i], &sbox[j]);
}
}

void RC4(unsigned char* data, unsigned int dataLen, const unsigned char key[]) {
unsigned char k, i = 0, j = 0, t;
init_sbox(key);
for (unsigned int h = 0; h < dataLen; h++) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;
swap(&sbox[i], &sbox[j]);
t = (sbox[i] + sbox[j]) % 256;
k = sbox[t];
data[h] ^= k;
}
}

int main(void) {
unsigned int dataLen = sizeof(data) / sizeof(data[0]);
RC4(data, dataLen, key);
for (unsigned int i = 0; i < dataLen; i++) {
printf("%c", data[i]);
}
return 0;
}

官方动调方法1

alt text
alt text

from ida_bytes import *
# addr = 0x56201B813040 # 这里需要填写自己动调时得到的地址
enc = [0xC4, 0x60, 0xAF, 0xB9, 0xE3, 0xFF, 0x2E, 0x9B, 0xF5, 0x10,
0x56, 0x51, 0x6E, 0xEE, 0x5F, 0x7D, 0x7D, 0x6E, 0x2B, 0x9C,
0x75, 0xB5]
for i in range(22):
patch_byte(addr + i, enc[i])
print('Done')

alt text

drink_tea

Week2 - Reverse 逆向工程
简单
出题人:Chovy
来喝茶吧

alt text

#include <stdio.h>
#include <stdint.h>

// 解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], i;
uint32_t delta = 2654435769;
uint32_t sum = (32) * delta;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) { // 解密时将加密算法的顺序倒过来,+= 变为 -=
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; // 解密后再重新赋值
}


unsigned char keys[] = "WelcomeToNewStar";
unsigned char cipher[] = { 0x78,0x20,0xF7,0xB3,0xC5,0x42,0xCE,0xDA,0x85,0x59,0x21,0x1A,0x26,0x56,0x5A,0x59,0x29,0x02,0x0D,0xED,0x07,0xA8,0xB9,0xEE,0x36,0x59,0x11,0x87,0xFD,0x5C,0x23,0x24 };
int main()
{
unsigned char a;
uint32_t* v = (uint32_t*)cipher;
uint32_t* k = (uint32_t*)keys;
// v 为要加密的数据是 n 个 32 位无符号整数
// k 为加密解密密钥,为 4 个 32 位无符号整数,即密钥长度为 128 位

for (int i = 0; i < 8; i += 2)
{
decrypt(v + i, k);
// printf("解密后的数据:%u %u\n", v[i], v[i+1]);
}

for (int i = 0; i < 32; i++) {
printf("%c", cipher[i]);
}

return 0;
}

Ptrace

Week2 - Reverse 逆向工程
中等
出题人:nuthecz
ptrace 是什么?

ptrace是Linux系统中的一个强大系统调用,用于观察和控制另一个进程的执行,广泛应用于调试和系统调用跟踪。
允许一个进程(称为tracer)观察和控制另一个进程(称为tracee)的执行。通过ptrace,tracer可以检查和修改tracee的内存和寄存器状态。这一功能使得ptrace成为调试工具(如GDB)和系统调用追踪工具(如strace)的基础。

alt text

  • 子进程对应地址找到函数

alt text

#include<stdio.h>

int main() {
int input[32] = { 204,141,44,236,111,136,237,235,47,237,174,235,78,172,44,141,141,47,235,109,205,237,238,235,14,142,78,44,108,172,231,175 };
for (int i = 0; i < 32; i++) {

input[i] = (input[i] << 3) | (input[i] >> 5);
printf("%c", input[i]);
}

return 0;
}
a=[0xCC, 0x8D, 0x2C, 0xEC, 0x6F, 0x88, 0xED, 0xEB, 0x2F, 0xED,
0xAE, 0xEB, 0x4E, 0xAC, 0x2C, 0x8D, 0x8D, 0x2F, 0xEB, 0x6D,
0xCD, 0xED, 0xEE, 0xEB, 0x0E, 0x8E, 0x4E, 0x2C, 0x6C, 0xAC,
0xE7, 0xAF]
for i in range(len(a)):
a[i]=((a[i]>>5)|(a[i]<<3)%256)
print(chr(a[i]),end="")

PangBai 泰拉记(1)

Week2 - Reverse 逆向工程
简单
出题人:straw
PangBai 在游玩泰拉瑞亚时,想要做一个红石计数器来记录自己离开孤儿院的的天数,做完后却发现一直运行不了。这时候她想:哎,要是个调试器,决定每一步能不能通过,那该有多好啊。

  • 前置函数看到反调试CheckRemoteDebuggerPresent + IsDebuggerPresent

alt text
alt text

  • jz改jnz,下断点直接运行

alt text
alt text

  • 直接拿到flag
  • 至于官方提到的解法3:装自动绕过反调试插件,小幽灵
  • 尝试了一下scyllahide插件没有ida9的插件。。。
  • 选择dbg装这个插件后面遇到题目再实战吧有点不会用

011vm

Week3 - Reverse 逆向工程
中等
出题人:kw17
欢迎来到混淆专场

  • d810装起来对ida9不是很友好,ai搞了下,存档
  • 也没有完全反编译完美,轮数还是混淆了

alt text

  • 未魔改tea

alt text

  • 实在搞不明白key和原文的逻辑混淆的很厉害了(晕倒
  • 官方的是c++解法
  • c的↓
#include <stdio.h>
#include <stdint.h>
#include <string.h>

void TEA_decrypt(uint32_t v[2], const uint32_t key[4]) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, delta = 0x9e3779b9;
for (int i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3]);
v0 -= ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1]);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}

void uint32_to_string(const uint32_t decrypted[8], char* result) {
int idx = 0;
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 4; ++j) {
char byte = (decrypted[i] >> (8 * j)) & 0xFF;
result[idx++] = byte;
}
}
result[idx] = '\0';
}

int main() {
uint32_t key[4] = { 0x11121314, 0x22232425, 0x33343536, 0x41424344 };

uint32_t encrypted_flag[8] = {
0x38b97e28, 0xb7e510c1, 0xb4b29fae, 0x5593bbd7,
0x3c2e9b9e, 0x1671c637, 0x8f3a8cb5, 0x5116e515
};

for (int i = 0; i < 8; i += 2) {
TEA_decrypt(&encrypted_flag[i], key);
}

char decrypted_flag[33];
uint32_to_string(encrypted_flag, decrypted_flag);

printf("Decrypted flag: %s\n", decrypted_flag);

return 0;
}

PangBai 过家家(3)

Week3 - Reverse 逆向工程
简单
出题人:0xA1pha
PangBai 住院了,医生说他体内大量的丙酮酸羧化酶(PYC)基因被 DNA 内切酶所「解开」,导致丙酮酸难以羧化为草酰乙酸,从而阻止了糖异生和谷氨酸生成,导致神经递质分泌不足并引发昏厥症状。医生根据条斑紫菜叶状体中的 PyPYC 序列构建了能够通过 MCT4 转运蛋白、含 PYC 基因的病毒体对 PangBai 进行注射,两个系统时后,PangBai 体内葡萄糖和胰岛素水平恢复正常,相关二元反射均正常。医生和我说可以准备出院手续了。(以上内容不包含专业性医学建议或指导)

  • 常规pyinstaller打包反编译pyc得到
import sys
print('Welcome to NewStar~')
print('Please input the flag:')
enc = [40, 9, 22, 52, 15, 56, 66, 71, 111, 121, 90, 33, 18, 40, 3, 13, 80, 28, 65, 68, 83, 88, 34, 86, 5, 12, 35, 82, 67, 3, 17, 79]
key = 'NewStar2024'
input = input('> ')
if len(input) != len(enc):
print('Wrong flag, try again!')
sys.exit(0)
for i in range(len(input)):
if enc[i] != ord(input[i]) ^ ord(key[i % len(key)]):
print('Wrong flag, try again!')
sys.exit(0)
print('Correct flag!')
  • 写脚本
enc = [40, 9, 22, 52, 15, 56, 66, 71, 111, 121, 90, 33, 18, 40, 3, 13, 80, 28, 65, 68, 83, 88, 34, 86, 5, 12, 35, 82, 67, 3, 17, 79]
key = 'NewStar2024'
flag = [0]*len(enc)
for i in range(len(enc)):
flag[i] = chr(enc[i] ^ ord(key[i % len(key)]))
print(''.join(flag))

SMc_math

Week3 - Reverse 逆向工程
简单
出题人:tgrddf55
Simultaneous Multivariate Calculations ——我才不会告诉你 SMC 其实是双关呢!

smc,自修改代码

alt text

  • 动调
    • 记住要选择后按u

alt text

  • idc脚本(shift + F2)
auto addr = 0x11E9;
auto i = 0;
for(i;i <= 0x3d5; i++){
PatchByte(addr+i,Byte(addr+i) ^ 0x3e);
}

alt text

from z3 import *
import struct
a = [Int(f'a{i}') for i in range(7)]

constraints = [
5 * (a[1] + a[0]) + 4 * a[2] + 6 * a[3] + a[4] + 9 * a[6] + 2 * a[5] == 0xD5CC7D4FF,
4 * a[6] + 3 * a[3] + 6 * a[2] + 10 * a[1] + 9 * a[0] + 9 * a[5] + 3 * a[4] == 0x102335844B,
9 * a[4] + 4 * (a[3] + a[2]) + 5 * a[1] + 4 * a[0] + 3 * a[6] + 10 * a[5] == 0xD55AEABB9,
9 * a[1] + 5 * a[0] + 9 * a[6] + 2 * (a[2] + 2 * a[3] + 5 * a[4] + a[5]) == 0xF89F6B7FA,
5 * a[4] + 9 * a[3] + 7 * a[0] + 2 * a[1] + a[2] + 3 * a[6] + 9 * a[5] == 0xD5230B80B,
8 * a[6] + 6 * a[3] + 10 * a[2] + 5 * a[1] + 6 * a[0] + 3 * a[5] + 9 * a[4] == 0x11E28ED873,
a[0] + 4 * (a[2] + a[1] + 2 * a[3]) + 9 * a[4] + a[5] + 3 * a[6] == 0xB353C03E1
]

solver = Solver()
solver.add(constraints)

if solver.check() == sat:
m = solver.model()
x = [m[ai].as_long() for ai in a]
print('Raw values:', x)
print('Hex:', [hex(v) for v in x])

# 用 struct 打包成字节再解码
byte_data = b''.join(struct.pack('<I', value) for value in x)
result_string = byte_data.decode('ascii', errors='ignore')
print('Flag (struct):', result_string)
else:
print('no ans!')

SecertsOfKawaii

Week3 - Reverse 逆向工程
困难
出题人:PangBai
我的脑内恋碍选项正在全力妨碍你拿到 flag 喵

static {
// 加载名为 libezencrypt.so 的文件
// System.loadLibrary方法会自动根据运行的操作系统对参数进行包装:
// Android/Linux前面加上 lib,后面加上 .so ;
// Windows普通 Java 开发,后面加上 .dll
System.loadLibrary("ezencrypt");
}

alt text

  • jeb去混淆后看mainactivty
  • rc4 → base64 → so
  • rc4 key为 rc4k4y

alt text

  • 最开始apk丢die看到upx打包猜测,丢下so发现
  • 反编译so参考可猜测check函数命名

alt text

  • 跟进btea看到:

alt text

#include <stdio.h>
#include <stdint.h>

#define DELTA 0xDEADBEEF //标准值DELTA是 0x9E3779B9

#define MX (((z ^ key[e ^ p & 3]) + (y ^ sum)) ^ (((4 * z) ^ (y >> 3)) + ((8 * y) ^ (z >> 5))))
// 标准XXTEA MX:#define MX (((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t* v, int n, const uint32_t key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;

if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}

int main() {
uint32_t v[12] = { 0x8c12d3dfUL, 0x5f4c4137UL, 0x1a9d3d02UL, 0x2d1294b7UL, 0xfb622b37UL, 0xd18d84e3UL, 0x64c4592UL, 0x16985cabUL, 0xfdb06d69UL, 0xfb30b1e3UL, 0x925c2fd3UL, 0x2e1bb40cUL };

const uint32_t* k = (const uint32_t*)"meow~meow~tea~~~";

btea(v, -12, k);

printf("%s\n", (char*)v);
return 0;
}
//qGioT8ksbvHifioMYdq/hBspRL4CRzFVO/YbgNYdCg==

alt text

flowering_shrubs

Week3 - Reverse 逆向工程
中等
出题人:tgrddf55
乱花渐欲迷人眼。
alt text

  • 这段还可以理解,就是下回自己做要注意压栈也是很重要要包括的
  • 官方去花idapython脚本
import idc
import idaapi
startaddr=0x1100
endaddr=0x15FF
lis=[0x50, 0x51, 0x52, 0x53, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x48, 0x81, 0xC3, 0x12, 0x00, 0x00, 0x00, 0x48, 0x89, 0x5C, 0x24, 0x18, 0x48, 0x83, 0xC4, 0x18,0xC3]
#这个for循环是关键点,检测以当前地址开始的27个字节是否符合lis列表的内容。
for i in range(startaddr,endaddr):
flag=True
for j in range(i,i+27):
if idc.get_wide_byte(j)!=lis[j-i]:
flag=False
if flag==True:
for addr in range(i,i+27):
idc.patch_byte(addr,0x90) # 将这部分内容全部nop掉

for i in range(startaddr,endaddr):# 取消函数定义
idc.del_items(i)
for i in range(startaddr,endaddr): # 添加函数定义
if idc.get_wide_dword(i)==0xFA1E0FF3: #endbr64
idaapi.add_func(i)
  • 流密码

alt text

rand();                              // [丢弃] 第一次随机数(种子预热,常见做法)

do {
v1 = (rand() % 40) & 0xFC; // [生成] 0-39的随机数,然后对齐到4的倍数
} while ( byte_4080[v1] ); // [查重] 检查该位置是否已被使用

byte_4080[v1] = 1; // [标记] 标记该位置已使用
return v1; // [返回] 返回4字节对齐的偏移量
  • 可能结果:0, 4, 8, 12, 16, 20, 24, 28, 32, 36
  • 动调
lis=[0x54,0xf4,0x20,0x47,0xfc,0xc4,0x93,0xe6,0x39,0xe0,
0x6e,0x00,0xa5,0x6e,0xaa,0x9f,0x7a,0xa1,0x66,0x39,
0x76,0xb7,0x67,0x57,0x3d,0x95,0x61,0x22,0x55,0xc9,
0x3b,0x4e,0x4f,0xe8,0x66,0x08,0x3d,0x50,0x43,0x3e]
str="uarefirst."
offset_buf=[0,4,32,0xc,8,0x18,16,0x14,0x1c,0x24]
#offset_buf就是通过动态调试提取出每一轮get_next_rand函数的返回值得到的
truekey=[]
for i in str:
truekey.append(ord(i))
def decrypt(offset,key):
a=lis[offset]
b=lis[offset+1]
c=lis[offset+2]
d=lis[offset+3]
flagc=((c+key)&0xff)^b
flagd=c^d
flaga=a^d^key
flagb=((b-key)&0xff)^flaga^key
lis[offset]=flaga
lis[offset+1]=flagb
lis[offset+2]=flagc
lis[offset+3]=flagd
for i in range(10):
decrypt(offset_buf[i],truekey[i])
print(bytes(lis).decode('utf-8'))

alt text

  • 所以其实偏移是固定的

simpleAndroid

Week3 - Reverse 逆向工程
中等
出题人:nuthecz
到底是怎么加密的
alt text

// 标准跳转写法(固定模式)
Intent intent = new Intent(当前页面.this, 目标页面.class);
startActivity(intent); // 执行跳转

alt text

  • 长度要求+native标签函数
  • Java_包名_类名_方法名或者动态注册搜索JNI_OnLoad
// 静态注册 JNI 函数的标准格式:
Java_包名_类名_方法名(JNIEnv *env, jobject thiz, 参数1, 参数2, ...)

// 前两个参数是固定的:
// JNIEnv *env = JNI 环境指针(调用JNI API)
// jobject thiz = this 对象(Java中的当前对象)
// 从第三个开始才是 Java 传入的实际参数
  • 所以

alt text
alt text

  • 换表base64
  • 基于官方补充:

alt text

  • 密文:

alt text

import base64

enc = [
0xB2, 0x74, 0x45, 0x16, 0x47, 0x34, 0x95, 0x36, 0x17, 0xF4,
0x43, 0x95, 0x03, 0xD6, 0x33, 0x95, 0xC6, 0xD6, 0x33, 0x36,
0xA7, 0x35, 0xE6, 0x36, 0x96, 0x57, 0x43, 0x16, 0x96, 0x97,
0xE6, 0x16
]

for i in range(len(enc)):
enc[i] = (enc[i] << 4 | enc[i] >> 4) & 0xff

for i in range(len(enc)//2):
tmp = enc[i]
enc[i] = enc[len(enc) - i - 1]
enc[len(enc) - i - 1] = tmp

cipher = ''.join([chr(e) for e in enc])
new_table = "BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/A"
old_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print(base64.b64decode(cipher.translate(str.maketrans(new_table, old_table))))
  • python要& 0xff因为:
特性 C (uint8_t) Python (int)
整数类型 固定8位 无限精度(任意长度)
溢出行为 自动截断(模256) 不会溢出,无限增长
移位结果 保持8位 可能变成16位、32位…
  • v23 = __strlen_chk(StringUTFChars, -1);
    • 原型:size_t __strlen_chk(const char *str, size_t bufsize);
参数 说明
str 要计算长度的字符串
bufsize 缓冲区大小(边界检查)

取啥名好呢?

Week3 - Reverse 逆向工程
简单
出题人:路人甲
请看 CSAPP 这题解法很多,解出来就行了(没有答疑什么的,直接去看书)

alt text

  • nop再c转code,回main,u+p解决可以反编译了耶~~
  • 动调初步得到程序顺序

alt text

  • 第二遍动调还发现一个code 4的报错(?为什么前一次没有,maybe断点问题

alt text

longjmp是一种非局部跳转机制,可以从信号处理函数中跳回程序的其他位置,实现类似"异常恢复"的效果,longjmp 的跳转目标由 setjmp 设置

alt text

  • 梳理下逻辑(梳理不清楚,跟着官方走下
.text:00005643EA39A9B2  mov     eax, 0          ; eax = 0
.text:00005643EA39A9B7 call sub_5643EA39A1C0 ; 调用某个函数
.text:00005643EA39A9BC lea rax, env ; 加载 env 地址
.text:00005643EA39A9C3 mov rdi, rax ; 参数1 = &env
.text:00005643EA39A9C6 call sub_5643EA39A180 ; 这很可能是 setjmp!
.text:00005643EA39A9CB endbr64
.text:00005643EA39A9CF cmp eax, 4 ; 比较 eax 和 4
.text:00005643EA39A9D2 ja short def_5643EA39A9F4 ; 大于4则跳default
.text:00005643EA39A9D4 mov eax, eax
.text:00005643EA39A9D6 lea rdx, ds:0[rax*4]
  • setjmp 的返回值决定分支
    setjmp 的返回值规律:
    第一次调用:返回 0
    从 longjmp 跳回:返回 longjmp 的第二个参数(这里是 1)
  • cmp eax, 4这里是 switch-case 跳转表的判断逻辑
┌─────────────────────────────────────────┐
│ RAX │ 64位 (8字节)
│ ┌─────────────────────────────────┐ │
│ │ EAX │ │ 32位 (4字节)
│ │ ┌─────────────────────────┐ │ │
│ │ │ AX │ │ │ 16位 (2字节)
│ │ │ ┌─────────┬─────────┐ │ │ │
│ │ │ │ AH │ AL │ │ │ │ 各8位 (1字节)
│ │ │ │ (高8位) │ (低8位)│ │ │ │
│ │ │ └─────────┴─────────┘ │ │ │
│ │ └─────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘

alt text

  • 所以第一次返回值就是0

alt text

  • 没有搞懂为什么qword_555555558060 = (__int64)&dword_555555558068;在赋值233前面但是最后dword_555555558068的值是233(但是动调可以发现是0xe9
  • ok很好理解官方是c脚本我写个python的
a = [0x4f, 0x54, 0x48, 0x53, 0x60, 0x45, 0x37, 0x1a, 0x28, 0x41, 0x26, 0x16, 0x3b, 0x45, 0x14, 0x47, 0xe, 0xc, 0x70, 0x3b, 0x3c, 0x3d, 0x70]
for i in range(len(a)):
a[i]^=i
a[i]-=233
a[i] &= 0xFF
# 模仿c的unsigned char
# 8位无符号整数(0~255)溢出时会自动模256
a[i]=chr(a[i])
print(''.join(a))

MazE

Week4 - Reverse 逆向工程
中等
出题人:tgrddf55
又是经典迷宫题(最终 flag 为 flag{md5(path)},其中 md5 为 32 位小写)

  • 了解pipe:https://www.cnblogs.com/wuyepeng/p/9747557.html
  • pipe(pipedes) 后:
    pipedes[0] = 3 // 读端(只能read)
    pipedes[1] = 4 // 写端(只能write)
  • fork()返回值含义
    • -1:创建失败
    • 0:在子进程中返回
    • >0:在父进程中返回,值为子进程的PID

alt text

PlzDebugMe

Week4 - Reverse 逆向工程
中等
出题人:PangBai
你知道吗?眼睛看见的不一定是真的。你会用 Frida 吗?

easygui

Week4 - Reverse 逆向工程
简单
出题人:tgrddf55
终于不是黑框框了!

ezrust

Week4 - Reverse 逆向工程
中等
出题人:ATRI
椰奶曾经和 ATRI 说过,Rust 是世界上最安全最优美的语言,这不禁让 ATRI 幻想,我什么时候才能成为 Rust 糕手呢

洞 OVO

Week4 - Reverse 逆向工程
困难
出题人:Ajarbox
妹妹掉进洞里了,作为哥哥的你快来找找吧(开放性题目,做法很多)

Lock

Week5 - Reverse 逆向工程
简单
出题人:0xA1pha
0xA 锁住了一个秘密,快来解密吧!
PS: 本题如果运行不了,大概率是缺库。

MY_ARM

Week5 - Reverse 逆向工程
签到
出题人:tgrddf55
这是什么架构啊?

Ohn_flutter!!!

Week5 - Reverse 逆向工程
困难
出题人:PangBai
听说 flutter 很难逆向呢,你可以来试试吗

PangBai 泰拉记(2)

Week5 - Reverse 逆向工程
困难
出题人:straw
PangBai 在游玩泰拉瑞亚一个星期后,成功打过了最终 Boss 月球领主,月球领主给他发送了一串神秘代码:
alt text
好像是流程图?

PangBai 泰拉记(3)

Week5 - Reverse 逆向工程
困难
出题人:straw
PangBai 拥有了他的第一部手机,是台二手的 iPhone7,他想用这台手机来玩泰拉瑞亚,打开 App Store 一看还需要购买,于是他找到了 straw 学长。straw 学长答应他可以给他装一个盗版的,但是要解出这一道有关 Wwift 的题目,于是他收到了一个 ipa…(有越狱果子机或者 Xcode 的同学可以尝试安装)

jun…junkcode?

Week5 - Reverse 逆向工程
中等
出题人:a
花指令?不确定,再看看