极客大挑战2023 Reverse wp

shiftjmp

image-20231127153316530

64bit的ELF文件,IDA打开

image-20231127153427348

考察花指令去除、将E9 nop掉

image-20231127153527787

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~}

点击就送的逆向题

image-20231127155627200

64bit的ELF文件。

image-20231127155829215

做了一个简单的加法,逆向一下减去就好。

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

幸运数字

image-20231127161354600

image-20231127163210554

本来想试试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

image-20231127163257472

32bit C++文件

image-20231127163825518

去除花指令

全都是简单的jnz和jz互补跳转,将E8或者E9全部改为90就好,下面的有些数据转换成代码也是一样的操作。

之后记得把黄色的部分修复一下。

image-20231127164255173

之后得到正确的代码,一些数据和一些已知字符串。

sub点进去

image-20231127164345346

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自己再手动调整下。


小黄鸭

image-20231127173647234

pyinstaller编译的,考察py逆向,用pyinstxtractor解包

image-20231127173748985

image-20231127173812804

找到1.pyc,之后使用uncompyle6反编译

image-20231127173845051

image-20231127173907499

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

image-20231128001521714

image-20231128084901128

看到VirtualProtect,这个函数在windows中有修改内存读写权限的功能,它对sub_4013B0地址起的读写权限进行了修改。

image-20231128091348911

image-20231128092813878

直接动态调试,单步进入函数内。将起始处一直到第一个retn的汇编全部U掉,再转换成代码,反编译

image-20231128092922826

一个魔改的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文件

image-20231129135023004

用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文件。

image-20231129153936889

密文数据。

image-20231129154013245

动态调试发现,在94行做了+10的操作,后面text_47;跟进

image-20231129154132805

化简后就是,先异或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

image-20231129195517151

这里用了一个I0o0I函数,还有密文Sycloverforerver

用apktool解包,去逆so里的I0o0I函数,

image-20231129200055758

加密部分

image-20231129200111951

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}

浪漫至死不渝

image-20231129205304309

逆index.js ; vscode打开就好。

image-20231129205342727

image-20231129205355140

对 ‘53X211WH04N’ 进行三次的栅栏密码。

image-20231129205533000

得到5201314wxhn

之后就是线性代换:

image-20231129205502815

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打开

image-20231129213753550

image-20231129213835435

运行游戏的时候要用dnspy64,所以这里用dnspy64打开。看Gamemanager:

image-20231129213932952

image-20231129214120194

主要逻辑

image-20231129214132448

每扎一次针异或一次,所以这里不能通过修改分数来得到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())

image-20231129215548420


ezandroid

apk文件,用jadx打开;

image-20231205110601122

魔改的TEA,第一次加密的v1,继续作为第二组的v0加密。

分析代码,

image-20231205111340281

作了一个点击后的处理方法,如果字符串长度超过24就清空,为0或者不足24就自动往后面补充"X",。这个字符串对象名叫 sb。

image-20231205111607917

将sb,按照奇偶位分成了sb2和sb3。接着,对sb4,也就是sb2做了一个TEA加密。

image-20231205111645053

密文和key

image-20231205112636813

接着看,MainActivity2

image-20231205113217495

作了一个异或,使用了俩个对象,“ad@#E!@a123"和"eCAS213@!@3”。在MainActivity中可以看到

image-20231205113314430

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sciurdae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值