内网靶场天天练 - Re 方向

从低分到高分,把知识点都记录一下。

从100-500

100

1.1_IDA1_100

ida打开即有

1.1_IDA2_100

ida打开即有

0.1_adb_100

jadxgui 打开apk直接看逻辑

s = [ 113, 123, 118, 112, 108, 94, 99, 72, 38, 68, 72, 87, 89, 72, 36, 118, 100, 78, 72, 87, 121, 83, 101, 39, 62, 94, 62, 38, 107, 115, 106 ]
for i, c in enumerate(s):
    print(chr(c^23), end='')
# flag{It_1S_@N_3asY_@nDr0)I)1|d}

0.2_Jeb_100

jadxgui 打开apk直接看逻辑

p = [-40, -62, 107, 66, -126, 103, -56, 77, 122, -107, -24, -127, 72, -63, -98, 64, -24, -5, -49, -26, 79, -70, -26, -81, 120, 25, 111, -100, -23, -9, 122, -35, 66, -50, -116, 3, -72, 102, -45, -85, 0, 126, -34, 62, 83, -34, 48, -111, 61, -9, -51, 114, 20, 81, -126, -18, 27, -115, -76, -116, -48, -118, -10, -102, -106, 113, -104, 98, -109, 74, 48, 47, -100, -88, 121, 22, -63, -32, -20, -41, -27, -20, -118, 100, -76, 70, -49, -39, -27, -106, -13, -108, 115, -87, -1, -22, -53, 21, -100, 124, -95, -40, 62, -69, 29, 56, -53, 85, -48, 25, 37, -78, 11, -110, -24, -120, -82, 6, -94, -101];
q = [-57, -90, 53, -71, -117, 98, 62, 98, 101, -96, 36, 110, 77, -83, -121, 2, -48, 94, -106, -56, -49, -80, -1, 83, 75, 66, -44, 74, 2, -36, -42, -103, 6, -115, -40, 69, -107, 85, -78, -49, 54, 78, -26, 15, 98, -70, 8, -90, 94, -61, -84, 64, 112, 51, -29, -34, 126, -21, -126, -71, -31, -24, -60, -2, -81, 66, -84, 85, -91, 10, 84, 70, -8, -63, 26, 126, -76, -104, -123, -71, -126, -62, -23, 11, -39, 70, 14, 59, -101, -39, -124, 91, -109, 102, -49, 21, 105, 0, 37, -128, -57, 117, 110, -115, -86, 56, 25, -46, -55, 7, -125, 109, 76, 104, -15, 82, -53, 18, -28, -24];
for i, (a,b) in enumerate(zip(p,q)):
    print( chr((a & 255) ^( b & 255)), end='')
# DDCTF-3ad60811d87c4a2dba0ef651b2d93476@didichuxing.com

1.1_easy_mfc_100 #MFC

mfc程序,需要了解一些winapi。知道点击按钮触发哪个API.

随便输入提示 Error, ida打开程序 String搜索到
'Error',0
上面有个ok, x交叉定位

CWnd::SetDlgItemTextW(this, -1, L"OK");

用到 SetDlgItemTextW ,下次直接在 SetDlgItemTextW 下断点即可定位到关键位置。

SetDlgItemTextW: 设置指定控件的文本内容,同效果有 SetDlgItemTextA、SetDlgItemTextW

  *k2 = 0x928C9DBC;
  *&k2[4] = 0x21864740;
  *&k2[8] = 0xFD8FACF5;
  v3 = *(Str - 12) == 26;
  *&k2[12] = 0x3AE9E468;
  *&k2[16] = 0x64B366C0;
  *&k2[20] = 0x22D3797E;
  *&k2[24] = 0xF831;
  *k1 = 0xFDEEACD2;
  *&k1[4] = 0x79FD2C2F;
  *&k1[8] = 0x85D0DEC5;
  *&k1[12] = 0xBB6B658;
  *&k1[16] = 0x54C039F5;
  *&k1[20] = 0x54E21F21;
  *&k1[24] = 0x8502;
  if ( v3 )
  {
    i = 0;
    while ( (k2[i] ^ ATL::CSimpleStringT<wchar_t,1>::GetAt(&Str, i)) == k1[i] )
    {
      if ( ++i >= *(Str - 12) )
      {
        CWnd::SetDlgItemTextW(this, -1, L"OK");
      }

逻辑清晰就异即可

bh = lambda x: bytes.fromhex(x)
k1 = bh('BC9D8C9240478621F5AC8FFD68E4E93AC066B3647E79D32231F8')
k2 = bh('D2ACEEFD2F2CFD79C5DED08558B6B60BF539C054211FE2540285')
for _, (a, b) in enumerate(zip(k1, k2)):
    print(chr(a ^ b), end='')
# n1book{X0r_x0R_15_s0_f1v3}

1.2_apk文件结构_100

第一步
public boolean a(String str) {
try {
return ncheck(new a().a(str.getBytes()));
} catch (Exception e) {
return false;
}
}

new a() 点击进来
private static final char[] a = {'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'};
一眼看起来是base64换表 表为 i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN

第二步

    static {
        System.loadLibrary("native");
    }
    private native boolean ncheck(String str);

有native的方法是调用apk中的so文件中的方法, 解压apk有 armeabi-v7a\libnative.so
ida打开查看 Java_com_a_easyjni_MainActivity_ncheck

bool __fastcall Java_com_a_easyjni_MainActivity_ncheck(int a1, int a2, int a3)
点击方法按Y修改下类型
bool __fastcall Java_com_a_easyjni_MainActivity_ncheck(JNIEnv *a1, jobject a2, void *a3);
看起来容易很多

    for ( i = 0; i != 16; ++i )
    {
      v0i = &v12[i];
      v12[i] = Str1[i + 16];
      v16i = Str1[i];
      v0i[16] = v16i;
    }
    (*a1)->ReleaseStringUTFChars(a1, Str, Str1);
    j = 0;
    do
    {
      k = j < 30;
      v13 = v12[j];
      v12[j] = v12[j + 1];
      v12[j + 1] = v13;
      j += 2;
    }
    while ( k );
    return memcmp(v12, "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7", 0x20u) == 0;

前16和后16字符互换 AQOoMQFPskB1Bsc7MbT3sQgX039i3g==
然后每2个字符换位置 QAoOQMPFks1BsB7cbM3TQsXg30i9g3==

Cyberchef 用base64换表解一下
image

flag{just_ANot#er_@p3}

1.2_GDB1_100

一定要使用linux版本 用ida打开 task9_x86_64_46d01fe312d35ecf69c4ff8ab8ace75d080891dc, 有个长序列的key, 异或 0xDEADBEEF, flag 逆序按字节异或

import struct

raw_data = bytes.fromhex('54C87EE364C7169ACD1165322DE3D34392A99DD2E66D2CD3B6BDFE6A')
flag_data = bytes.fromhex('DC17BF5BD40AD21B7DDAA795B53210F61C65535367BAEA6E782272D3')

# 自动计算 4 字节整数的数量, 按原流程异或
count = len(raw_data) // 4
data = struct.unpack(f"<{count}I", raw_data)

for _, val in enumerate(data):
    v2 = val ^ 0xDEADBEEF
    v2_bytes = struct.pack("<I", v2)

    for j in range(3, -1, -1):
        print(chr(v2_bytes[j] ^ flag_data[4 * i + j]), end='')
# flag_is_you_know_cracking!!!

1.2_GDB2_100

32位程序。

有个if判断。可以用gdb调试修改来跳转。或者在ida里直接nop掉执行即可。

Give me maigc :CTF{debugger_1s_so_p0werful_1n_dyn4m1c_4n4lySis!}

2026-08-31-01 | 1.2_反调试_100 #MFC

直接看这里学一下。
https://bbs.csdn.net/weixin_29325007/article/details/100207552
但是多解。不知道哪个对。跳过

2026-08-31-02 | 1.3_OD1_100 #Delphi

od运行程序后 bp messageboxa, 点击到这里。直接栈里有flag.

image

2026-08-31-02 | 1.3_OD2_100 #Delphi

使用Interactive Delphi Reconstructor 来查看。
注册码的框有个keyup方法。在这里下断 bp 00457D35 。输入任意时直接有flag
00457D2F | 8B93 18030000 | mov edx,dword ptr ds:[ebx+318] | edx:"黑头Sun Bird11dseloffc-012-OKabcdef", [ebx+318]:"黑头Sun Bird9dseloffc-012-OKflag"
00457D35 | E8 52BFFAFF | call <ckme.sub_403C8C> |

不知道是不是flag格式有问题,跳过。

2026-08-31-03 | 1.3_OD3_100 #VB

VB decompiler 反编译下

def generate_key(name: str) -> int:
    # 计算所有字符 ASCII 码累加和,并乘以 1234567890
    ascii_sum = sum(ord(char) for char in name)
    k = str(ascii_sum * 1234567890)
    return f'{k[:3]}-{k[4:8]}-{k[-3:]}'

if __name__ == "__main__":
    name = input("Name: ").strip()
    if name:
        key = generate_key(name)
        print(f"Key: {key}")
    else:
        print("Name cannot be empty!")

不知道flag啥格式。

2026-08-31-04 | 1.3_test_packed_100 #UPX脱壳

方式1 detect it easy 查壳 upx, 脱壳命令
upx -d test_packed.exe

方式2 手动
ollydbg载入后F8 右键esp follow dump
左下角 dump 右击下硬件访问断, F9执行, 删除断点,一个大跳来到入口。(入口前如果有向下跳的可以。向上跳的,就在它下一行断点,断到下面)

2026-08-31-05 | 1.3_用as写一个app_100

jadx查看密码

for length in range(12):
    char_code = 107 - length
    print(chr(char_code), end='')
# kjihgfedcba`

输入后来了个图。好像不完整。翻到NextContent, 在apk assets目录下找到改成Jpg查看得到flag

flag{08067-wlecome}

2026-08-31-06 | 1.4_x64Dbg_100

ida直接看。何意味

2026-08-31-07 | 1.4_用as写一个so_100

jadx打开后
T.decode("MTgyNnN9MzJnaDNzZGIzNzhvaGpoe2dhbGY=", 0);
看着像base64
1826s}32gh3sdb378ohjh{galf 倒序
flag{hjho873bds3hg23}s6281
flag{hjh0873bd3sg23}

2026-08-31-08 | 1.5_HelloWorld

何意味

public class HelloWorld {  
    int a = 0;  
    static String b = "HelloDalvik";  
  
    public int getNumber(int i, int j) {  
        int e = 3;  
        return e + i + j;  
    }  
  
    public static void main(String[] args) {  
        int c = 1;  
        int d = 2;  
        HelloWorld helloWorld = new HelloWorld();  
        String sayNumber = String.valueOf(helloWorld.getNumber(c, d));  // 1+2+3 = 6
        System.out.println("HelloDex!" + sayNumber);   // HelloDex!6
    }  
}  

2026-08-31-09 | 1.6_apk1

和前面一样base64换表

image

2026-08-31-10 | 1.6_CFF1 #frida

使用frida修改数值, 我手机旧安装旧版

pc端: pip install frida==16.7.19
andrid: https://github.com/frida/frida/releases?page=9#release-16.7.19 下载 frida-server-16.7.19-android-arm64.xz, 将一个root过的手机连接电脑, 先安装 android sdk tools, 然后

adb push frida-server /sdcard/
su
pkill -9 frida-server
rm /data/local/tmp/frida-server

cd  /data/local/tmp/
mv /sdcard/frida-server ./
chmod +x ./frida-server
./frida-server

执行js

// frida -U -f com.ctf.test.ctf_100 -l l3.js

Java.perform(function () {
    var MainActivity = Java.use("com.ctf.test.ctf_100.MainActivity");
    MainActivity["Btn_up_onclick"].implementation = function (v) {
        if (this.has_gone_int.value < this.to_reach_int.value) {
            this.has_gone_int.value = this.to_reach_int.value - 1; 
        }
        this["Btn_up_onclick"](v);
    };
});

2026-09-01-01 | 1.10_babyre #RUST

    for ( i = 0; i < 0x26; ++i )
    {
      v16 = v13[i] ^ Str1[i];
      v22 = v16;
      n2 = 2;
      v24 = __ROL1__(v16, 2);
      v16 = v24;
...

      if ( s[i] != v17[i] )
        break;

v13异或 输入, 循环左移2 == v17
反过来即可。

ROR = lambda x, k=1: ((x >> k) | (x << (8 - k))) & 0xff
bh = lambda x: bytes.fromhex(x)
v1 = bh('279757E1A975663E1B63E3A0057359FB0A438FE0BAC0549906BF9F2FC4AAA6741EDD9722EDC5')
v2 = bh('19EBD8563300503561DC966FB50DA47A55E8FE5697DE9DAFD447AFC1C26A5AACB1A28A5952E2')
for _, (a, b) in enumerate(zip(v1, v2)):
    print(chr(a ^ ROR(b,2)), end='')
# amateursCTF{h0pe_y0u_w3r3nt_t00_ru5ty}

2026-09-01-02 | 1.10_hello #RUST

__int64 __fastcall sub_1400029C0(__int64 a1, BYTE *Str3, unsigned __int64 size2)
{
  v10[0] = 0xD2;
...
  while ( 1 )
  {
    v16 = sub_140004E70(v15);
    k = size2_3;
    if ( !v16 )
      break;
    size2_4 = k;
    v18[0] = v10[k] ^ Str3[k];
    if ( k < 30 )
      byte_140030000[k] ^= v18[0];
    v21 = v18[0];
    n2 = 2;
    v23 = __ROL1__(v18[0], 2);
  }
  return a1;
}

正确解出来的不是flag。最终比较值为 862B120F99CC1D55B739C5BEF3AB5D905F5F4CAFB62BF16CEDBE76149B888820A3A004
这里莫名多出个 byte_140030000 值会 ^ (v10[k] ^ Str3[k])。倒序回来这里
1.ROR 2
2. ^ byte_140030000[i]
会得到flag

ROR = lambda x, k=1: ((x >> k) | (x << (8 - k))) & 0xff
v10 = bytes.fromhex("D2A5F6B11F6C333D843D2EC68F84237BA3BF76B4CBA61D7C24DBF56C957D5661854D2F")
enc = bytes.fromhex("862B120F99CC1D55B739C5BEF3AB5D905F5F4CAFB62BF16CEDBE76149B888820A3A004")
byte_140030000 = bytes.fromhex("C0A7E5B703463526AE1A37D498DA391788E37D8FF2AE19490EDCE936825F")
for i in range(30):
    d = ROR(enc[i], 2)
    print(chr(byte_140030000[i] ^ d), end='')
# amateursCTF{d0n3_4nd_deRust3d}

2026-09-01-03 | 2.1_花指令

void sub_401014()
{
  JUMPOUT(0x401640);
}

ida汇编界面在函数头按下p 控制台提示
.text:0040191F: The function has undefined instruction/data at the specified address.

继续看汇编

.text:0040191D loc_40191D:                             ; CODE XREF: .text:0040193D↓j
.text:0040191D                 push    offset byte_428C54
.text:00401922                 call    _strlen
.text:00401927                 add     esp, 4
.text:0040192A                 push    eax
.text:0040192B                 push    offset byte_428C54
.text:00401930                 call    sub_40101E
.text:00401935                 add     esp, 0Ch
.text:00401938                 nop
.text:00401939                 jz      short loc_401948
.text:0040193B                 jnz     short loc_401948
.text:0040193D                 jmp     short near ptr loc_40191D+2   ; jz/jnz 那就是必跳, 这三行就nop掉
.text:0040193F ; ---------------------------------------------------------------------------
.text:0040193F                 push    eax
.text:00401940                 mov     eax, ds:__imp_MessageBoxA
.text:00401945                 call    eax ; __imp_MessageBoxA
.text:00401947                 pop     eax
int __stdcall sub_401B20(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch ( uMsg )
  {
    case WM_INITDIALOG:
      return 1;
    case WM_COMMAND:
      if ( (unsigned __int16)wParam != 1 && (unsigned __int16)wParam != 2 )
        goto LABEL_6;
      EndDialog(hwndDlg, (unsigned __int16)wParam);
      return 1;
    case WM_LBUTTONUP:
LABEL_6:
      buf[dword_428C50++] = 0x31;               // 左键抬起 追加 0x31
      return 0;
    case WM_RBUTTONUP:
      buf[dword_428C50++] = 0x33;               // 右键抬起 追加 0x33
      return 0;
    case WM_MBUTTONUP:
      if ( n3 < 3 )
        ++dword_428D5C;
      buf[dword_428C50++] = 0x32;               // 中键抬起 追加 0x32
      return 0;
    default:
      return 0;
  }
}

Resource hacker

109 MENU

LANGUAGE LANG_CHINESE, 0x2
{
POPUP "&File"
{
	MENUITEM "E&xit",  105
}
POPUP "&Help"
{
	MENUITEM "&About ...",  104
}
}
LRESULT __stdcall sub_401640(HWND hWndParent, unsigned int Msg, WPARAM wParam, LPARAM lParam)
{

  if ( Msg > WM_COMMAND )
  {
    if ( Msg == WM_RBUTTONUP )
    {
      if ( strlen((const char *)::buf) > 6 ) // 不超过6个命令
        ExitProcess(0);
      if ( strlen((const char *)::buf) )
      {
      ...
        MD5(::buf, dwDataLen, (LPSTR)::buf);
        strcpy(Str, "0kk`d1a`55k222k2a776jbfgd`06cjjb");
        memset(&Str[33], 0, 0xDCu);
        strcpy(vSS, "SS");
        n32 = strlen(Str);
        sub_401005(vSS, (BYTE *)Str, n32); // Str和SS异或
        if ( _strcmpi((const char *)::buf, Str) )
        {
          SetWindowTextA(hWndParent, "flag{}");
          MessageBoxA(hWndParent, "Are you kidding me?", "^_^", 0);
          ExitProcess(0);
        }
        memcpy(lpText, &unk_423030, 0x32u);
        n32_1 = strlen(lpText);
        sub_401005(buf, (BYTE *)lpText, n32_1); // flag解密 用 md5 进行异或
        MessageBoxA(hWndParent, lpText, 0, 0x32u); 
      }
      ++n16;
    }
    else {...}
  }
  else
  {
    switch ( Msg )
    {
      case WM_COMMAND:
        wParam_1 = (unsigned __int16)wParam;
        v27 = HIWORD(wParam);
        if ( (unsigned __int16)wParam == 104 )  // About
        {
          DialogBoxParamA(hInstance, (LPCSTR)0x67, hWndParent, (DLGPROC)DialogFunc, 0); // 这里是输入指令的地方 对应 sub_401B20
        }
        ...
    }
  }
  return 0;
}

梳理逻辑。进入 about 输入6个以内字符。
然后 用0kk`d1a`55k222k2a776jbfgd`06cjjbSS 进行异或值为MD5 c8837b23ff8aaa8a2dde915473ce0991
6个字符的MD5为 c8837b23ff8aaa8a2dde915473ce0991

爆破或者 cmd5 查一下

from itertools import product
import hashlib

md5 = lambda x: hashlib.md5(x).hexdigest()

m1 = "c8837b23ff8aaa8a2dde915473ce0991"
dic = b'123'

for tp in product(dic, repeat=6):
    password = bytes(tp)
    m2 = md5(password)
    if m2 == m1:
        print(password)
        break
# 123321 即 左中右右中左

方式1:
进入 about 依次按键 左中右右中左
关闭about, 右击界面 出现flag

flag{n0_Zu0_n0_die}

方式2:

密文16进制 575E5254495F016D6946026E5F026C575B544C
和 123321 进行异或

2026-09-01-04 | 1.9_fridajava

jadxgui打开

package com.ad2001.frida0x2;
public class MainActivity extends AppCompatActivity {
    static TextView t1;
    public static void get_flag(int a) throws BadPaddingException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
        if (a == 4919) {
            try {
                SecretKeySpec secretKeySpec = new SecretKeySpec("HILLBILLWILLBINN".getBytes(), "AES");
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                IvParameterSpec iv = new IvParameterSpec(new byte[16]);
                cipher.init(2, secretKeySpec, iv);
                byte[] decryptedBytes = cipher.doFinal(Base64.decode("q7mBQegjhpfIAr0OgfLvH0t/D0Xi0ieG0vd+8ZVW+b4=", 0));
                String decryptedText = new String(decryptedBytes);
                t1.setText(decryptedText);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

image

2026-09-01-05 | 1.9_fridaso

image

2026-09-01-06 | 1.9_fridasostring

jadxgui查看有native函数,是get_flag

JNIEnv *__fastcall get_flag(JNIEnv *result, int a2)
{
  int i; // [xsp+Ch] [xbp-44h]
  char v3[20]; // [xsp+34h] [xbp-1Ch] BYREF
  __int64 v4; // [xsp+48h] [xbp-8h]

  v4 = *(_QWORD *)(_ReadStatusReg(TPIDR_EL0) + 40);
  if ( (_DWORD)result + a2 == 3 )
  {
    for ( i = 0; i < __strlen_chk("FPE>9q8A>BK-)20A-#Y", 0xFFFFFFFFFFFFFFFFLL); ++i )
      v3[i] = aFpe9q8aBk20aY[i] + 2 * i;
    v3[19] = 0;
    result = (JNIEnv *)__android_log_print(3, "FLAG", "Decrypted Flag: %s", v3);
  }
  _ReadStatusReg(TPIDR_EL0);
  return result;
}
enc = b"FPE>9q8A>BK-)20A-#Y"
for i, c in enumerate(enc):
    print(chr(c + i*2), end='')
# FRIDA{DONT_CALL_ME}

2026-09-01-07 | 2.1_attachment

pycdc 恢复下逆回去即可

cipher = ["\x1f", "\x12", "\x1d", "(", "0", "4", "\x01", "\x06", "\x14", "4", ",", "\x1b", "U", "?", "o", "6", "*", ":", "\x01", "D", ";", "%", "\x13", ]
code = [ord(c) for c in cipher]
l = len(code)

for i in range(l)[::-1]:
    code[i - 1] = code[i] ^ code[i - 1]

input1_chars = []
for i in range(l):
    # num = (input1[i] + i) % 128  =>  input1[i] = (num - i) % 128
    print(chr((code[i] - i) % 128), end='')

2026-09-01-08 | 2.2_main


import base64
target_base64 = 'wM/Cya0b08LMlZeW2g5SEcKWjuyRlx3Og5yMgLsR6pLCwLTQkIfHHJHe'
crypt2 = base64.b64decode(target_base64)


def decrypt_rc4_variant(data):
    sbox = list(range(256))
    key = '1234'
    j = 0
    for i in range(256):
        j = (j + sbox[i] + ord(key[i % len(key)])) & 255
        sbox[i] = sbox[j]
        sbox[j] = sbox[i]

    decrypted_bytes = bytearray()
    x = y = 0
    for idx in data:
        x = (x + 1) & 255
        y = (y + sbox[x]) & 255
        sbox[x] = sbox[y]
        sbox[y] = sbox[x]
        k = sbox[(sbox[x] + sbox[y]) & 255]
        decrypted_bytes.append(idx ^ k ^ 17)
    return decrypted_bytes

crypt1 = decrypt_rc4_variant(crypt2)
print(crypt1.hex())

key11不知道。爆破一下。
image

flag{81a2645d-12a5-234c-ab2b-241acb23aeb2}

2026-09-01-10 | 2.3_SEH1

SEH学习

push 0040105A:将异常处理回调函数(Handler)地址压栈。
push dword ptr fs:[0]:将旧的 SEH 链表头指针压栈。
mov dword ptr fs:[0], esp:更新 fs:[0],使其指向新的 SEH 节点(包含指针和 Handler)。

.text:00401017 xor     eax, eax
.text:00401019 mov     dword ptr [eax], 1 ; 触发异常跳转 0040105A

需要处理反调试。

2026-09-02-01 | Sprite License #TEA

标准tea解密

"""
[*] Metadata chunk content (TEA key):
    deadbeef13371337cafecafe42424242

[*] License chunk (encrypted):
7317a22dbccd585167648078eb4fd4814350d96b72d3a1041824d67a7d4d09ca

[!] License data is encrypted.
[!] Use the metadata key to decrypt.

[*] TEA encryption algorithm uses:
    - 64-bit blocks (8 bytes)
    - 128-bit key (16 bytes)
    - 32 rounds
    - Delta constant: 0x9e3779b9
"""
def decrypt(v, k):
    v0, v1 = v
    delta = 0x9E3779B9
    # x = sum(delta for _ in range(32)) & 0xFFFFFFFF
    x = delta * 32 & 0xffffffff
    k0, k1, k2, k3 = k
    for i in range(32):
        v1 -= ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)
        v1 = v1 & 0xFFFFFFFF
        v0 -= ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
        v0 = v0 & 0xFFFFFFFF
        x -= delta
        x = x & 0xFFFFFFFF
    return [v0, v1]


if __name__ == '__main__':

    import struct
    key1 = bytes.fromhex('deadbeef13371337cafecafe42424242')
    key = struct.unpack(f'<{len(key1)//4}I', key1)

    values = bytes.fromhex('7317a22dbccd585167648078eb4fd4814350d96b72d3a1041824d67a7d4d09ca')
    values = struct.unpack(f'<{len(values)//4}I', values)

    result = b''
    for i in range(0, len(values), 2):
        v = values[i:i + 2]
        r = decrypt(v, key)
        a,b = r # type:int,int
        ra,rb = struct.pack('<I', a),struct.pack('<I', b)
        result += ra + rb
    print(result)
# b'flag{spr1t3_t34_d3crypt_m4st3r}\x00'

2026-09-02-02 | AES Debugger Lab #AES

sub_401FD0(key, v15);
sub_4020F0(enc_data, &dword_4C32C0, v15);
sub_4020F0(&enc_data[16], &unk_4C32D0, v15);

提取key encdata出来直接解

image

2026-09-02-03 | babyRE #idapython

给了ida中的脚本 粘贴到控制台2次回车, 目标位置 0x600b00 处 按p创建函数

s=0x600b00
for i in range(182):
    patch_byte(s+i,get_db_byte(s+i)^0xc)
__int64 __fastcall judge(__int64 a1)
{
  _BYTE fmcd[5]; // [rsp+8h] [rbp-20h] BYREF
  _BYTE k7d_V__np[9]; // [rsp+Dh] [rbp-1Bh] BYREF
  int i; // [rsp+24h] [rbp-4h]

  qmemcpy(fmcd, "fmcd", 4);
  fmcd[4] = 127;
  qmemcpy(k7d_V__np, "k7d;V`;np", sizeof(k7d_V__np));
  for ( i = 0; i <= 13; ++i )
    *(_BYTE *)(i + a1) ^= i;
  for ( i = 0; i <= 13; ++i )
  {
    if ( *(_BYTE *)(i + a1) != fmcd[i] )
      return 0;
  }
  return 1;
}

exp

fmcd = [ord(c) for c in "fmcd"] + [127]  # 前 5 字节
k7d_V__np = [ord(c) for c in "k7d;V`;np"]  # 后 9 字节

target = fmcd + k7d_V__np

for i in range(len(target)):
    print(chr(target[i] ^ i), end='')
# flag{n1c3_j0b}

2026-09-02-04 | Base64 Shuffle #base64

看 decode_flag(v5, 64);

encoded_flag[i] ^ 0x5A;
// flag{b4s364_4lph4b3t_p3rmu4t10n_m4st3r}

2026-09-02-05 | bin #反调试antiDebug

里面有各种检测比较适合练习, 最后有个base85

;aj&@:JQ7HBOt[h?U8aCBk]OaI38
SECCON{check_Ascii85} 

2026-09-04-01 | 2.5_tttea_100 #反调试antiDebug #xxtea

有两处tls反调试 然后就是一个xxtea加密

int __stdcall TlsCallback_0_0(int a1, int a2, int a3)
{
  if ( !ProcessInformation_ )
  {
    DELTA = 0x66403319;
    return 1;
  }
  return result;
}

int *__stdcall TlsCallback_1_0(int a1, int a2, int a3)
{
  int *BeingDebugged_1; // eax
  signed __int8 BeingDebugged; // [esp+EBh] [ebp-5h]

  BeingDebugged = NtCurrentPeb()->BeingDebugged;
  BeingDebugged_1 = (int *)BeingDebugged;
  if ( !BeingDebugged )
  {
    DELTA ^= 0x12345678u;
    return &DELTA;
  }
  return BeingDebugged_1;
}

exp

import struct

# 1. 给定的密文 HEX
cipher_hex = "0323222F3688FD4321E85B65311E3BA64BB8DC888019846F97722126AD64EEBB88044D062F26E56B814BF573"
cipher_bytes = bytes.fromhex(cipher_hex)

# 转换成 11 个 32 位无符号整数 (Little-Endian)
v = list(struct.unpack("<11I", cipher_bytes))
n = len(v)

# 2. 确定 DELTA 及 Key
DELTA = 0x66403319 ^ 0x12345678  # 0x74746561
key = struct.pack("<I", DELTA)    # b'aett'

rounds = 52 // n + 6              # 10 轮
sum_val = (rounds * DELTA) & 0xFFFFFFFF

# 3. 逆向 XXTEA 解密循环
for r in range(rounds):
    e = (sum_val >> 2) & 3
    
    # 解密最后一个元素 v[n-1]
    z = v[0]
    y = v[n-2]
    i = n - 1
    k = key[e ^ (i & 3)]
    
    mx = (((y ^ k) + (z ^ sum_val)) & 0xFFFFFFFF) ^ \
         ((((16 * y) & 0xFFFFFFFF) ^ (z >> 3)) + (((4 * z) & 0xFFFFFFFF) ^ (y >> 6))) & 0xFFFFFFFF
    
    v[n-1] = (v[n-1] - mx) & 0xFFFFFFFF
    
    # 解密其余元素 v[n-2] 到 v[0]
    for i in range(n - 2, -1, -1):
        z = v[i + 1]
        y = v[i - 1] if i > 0 else v[n - 1]
        k = key[e ^ (i & 3)]
        
        mx = (((y ^ k) + (z ^ sum_val)) & 0xFFFFFFFF) ^ \
             ((((16 * y) & 0xFFFFFFFF) ^ (z >> 3)) + (((4 * z) & 0xFFFFFFFF) ^ (y >> 6))) & 0xFFFFFFFF
        
        v[i] = (v[i] - mx) & 0xFFFFFFFF
        
    sum_val = (sum_val - DELTA) & 0xFFFFFFFF

# 4. 转换为字符串
flag = struct.pack("<11I", *v).decode('utf-8')
print("Flag:", flag)

2026-09-04-02 | 2.6_CSHOP_100 #脱壳 #.NET

die查壳有壳 dotfuscator

de4dot.exe crackme.exe -o a.exe

private void button1_Click(object sender, EventArgs e)
{
	int[] array = new int[] { 123, 148, 62, 53, 24, 116, 244, 126, 63, 90 };
	string text = ((TextBox)base.Controls.Find("textBox1", false)[0]).Text;
	int[] array2 = new int[10];
	int[] array3 = new int[10];
	if (text.Length == 10)
	{
		for (int i = 0; i < text.Length; i++)
		{
			array2[i] = (int)text[i];
			byte b = (byte)(array2[i] & 7);
			byte b2 = (byte)((array2[i] >> 3) & 255);
			array3[i] = ((int)b << 5) | (int)b2;
			array3[i] ^= 18;
			if (array3[i] != array[i])
			{
				MessageBox.Show("Wrong!");
				return;
			}
		}
		MessageBox.Show("Success!");
		return;
	}
	MessageBox.Show("Wrong!");
}

exp

target_array = [123, 148, 62, 53, 24, 116, 244, 126, 63, 90]
for val in target_array:
    v1 = val ^ 18
    
    # array3[i] = (b << 5) | b2
    b = (v1 >> 5) & 7
    b2 = v1 & 31
    
    # b = C & 7, b2 = (C >> 3) & 255
    char_code = (b2 << 3) | b
    
    print(chr(char_code), end='')
# K4a9P37ciB
posted @ 2026-08-30 16:55  wgf4242  阅读(8)  评论(0)    收藏  举报