【2023春节】解题领红包 Windows 和 Android 初级解题过程记录

查看 90|回复 8
作者:Ganlv   
Windows 初级
拖到 ida 里,看着就像把输入值和一个常量的每个字节右移 2 位作比较,然后输出 Success。


Windows简单题.gif (3.04 MB, 下载次数: 0)
下载附件
2023-2-8 02:46 上传

Array.from(`98 01 00 00 B0 01 00 00  84 01 00 00 9C 01 00 00
EC 01 00 00 D4 00 00 00  C8 00 00 00 40 01 00 00
BC 01 00 00 28 01 00 00  A4 01 00 00 94 01 00 00
C8 00 00 00 C0 00 00 00  C8 00 00 00 CC 00 00 00
20 01 00 00 84 01 00 00  C0 01 00 00 C0 01 00 00
E4 01 00 00 38 01 00 00  94 01 00 00 DC 01 00 00
64 01 00 00 94 01 00 00  84 01 00 00 C8 01 00 00
F4 01 00 00 00 00 00 00  00 00 00 00 00 00 00 00`.matchAll(/.. .. .. ../g))
    .map(x => x[0])
    .map(x => x.split(' ').reverse().join(''))
    .map(x => parseInt(x, 16) >> 2)
    .map(x => String.fromCodePoint(x))
    .join('')
Android 初级题 1
拖到 jadx-gui 中,把那个字符串每个 ASCII 码减 2。


Android简单题1.gif (2.76 MB, 下载次数: 0)
下载附件
2023-2-8 02:46 上传

"hnci}|jwfclkczkppkcpmwckng\u007f".split('').map(x => x.codePointAt(0) - 2).map(x => String.fromCharCode(x)).join('')
Android 初级题 2
拖到 jadx-gui 中,uid + "Wuaipojie2023" 从后往前异或 5252...,然后 base64,然后 md5,然后恺撒密码挪动 5 位。
const script = document.createElement("script");
script.setAttribute("src", "https://unpkg.com/blueimp-md5/js/md5.min.js");
document.body.appendChild(script);
const uid = '765171';
`flag{${md5(btoa(`${uid}Wuaipojie2023`.split('').reverse().map((c, i) => String.fromCodePoint(c.codePointAt(0) ^ '52'.codePointAt(i % 2))).reverse().join(''))).replace(/[A-Za-z]/g, (c) => String.fromCodePoint((c.codePointAt(0) & 0xe0) + ((c.codePointAt(0) & 0x1f) + 5) % 26))}}`;

A 是 0b01000001,a 是 0b01100001,所以可以使用 0b11100000 (0xe0) 和 0b00011111 (0x1f) 进行位运算。
其他
Windows 中级和 Android 中级其实也做出来了,不调试过程太复杂了,不想写了。
Windows 中级
用 Rust 写的编码程序
fn new_uid_secret_table(k: u32) -> [u32; 4] {
    let mut result = [0u32; 4];
    for i in 0..4 {
        result = (i as u32 + 1).wrapping_mul(k + 1);
    }
    result
}
const FLAG_TEMPLATE: &[u8] = b"flag{!!!!_HAPPY_NEW_YEAR_2023!!!!}";
fn main() {
    println!("Hello, world!");
    let flag = BASE_TABLE.iter().enumerate().map(|(i, x)| *x ^ ((i as u32 + 1) * 0x11111111)).collect::();
    let flag_bytes = unsafe { &*slice_from_raw_parts(flag.as_ptr() as *const u16, BASE_TABLE.len() * 2) };
    println!("{}", String::from_utf16_lossy(flag_bytes));
    let k = generate_k(765171);
    let lparam = k.wrapping_mul(32);
    println!("k = 0x{:x} lparam = 0x{:x}", k, lparam);
    let uid_secret_table = new_uid_secret_table(k);
    println!("uid_secret_table = {:#x?}", uid_secret_table);
    let mut flag_u32v = Vec::from(unsafe { &*slice_from_raw_parts(FLAG_TEMPLATE.as_ptr() as *const u32, 8) });
    println!("flag_u32v = {:08x?}", flag_u32v);
    for i in (0..8).step_by(2) {
        let mask = encrypt_key_u32vec(&mut flag_u32v[i..], &uid_secret_table, k);
        println!("mask = {}", mask);
    }
    println!("flag_u32v = {:08x?}", flag_u32v);
    for i in (0..8).step_by(2) {
        println!("k.wrapping_mul(32) = {}", k.wrapping_mul(32));
        decrypt_key_u32vec(&mut flag_u32v[i..], &uid_secret_table, k, k.wrapping_mul(32));
    }
    println!("flag_u32v = {:08x?}", flag_u32v);
}
fn encrypt_key_u32vec(key_u32vec: &mut [u32], uid_secret_table: &[u32; 4], k: u32) -> u32 {
    let mut key0 = key_u32vec[0];
    let mut key1 = key_u32vec[1];
    let mut mask = 0u32;
    for _ in 0..32 {
        mask = mask.wrapping_add(k);
        key0 = key0.wrapping_add((uid_secret_table[1].wrapping_add(key1 >> 5)) ^ (mask.wrapping_add(key1)) ^ (uid_secret_table[0].wrapping_add(key1 > 5)) ^ (mask.wrapping_add(key0)) ^ (uid_secret_table[2].wrapping_add(key0  u32 {
    let mut key0 = key_u32vec[0];
    let mut key1 = key_u32vec[1];
    for i in 0..32 {
        key1 = key1.wrapping_sub((uid_secret_table[3].wrapping_add(key0 >> 5)) ^ (mask.wrapping_add(key0)) ^ (uid_secret_table[2].wrapping_add(key0 > 5)) ^ (mask.wrapping_add(key1)) ^ (uid_secret_table[0].wrapping_add(key1
Android 中级
用 Golang 写的解码程序。
package main
import (
        "bytes"
        "crypto/aes"
        "encoding/base64"
        "encoding/hex"
        "fmt"
        "io"
        "os"
)
func main() {
        image1, err := os.ReadFile("aes.png")
        if err != nil {
                panic(err)
                return
        }
        image2, err := base64.StdEncoding.DecodeString(string(image1))
        if err != nil {
                return
        }
        err = os.WriteFile("aes2.png", image2, 0644)
        if err != nil {
                panic(err)
                return
        }
        key1 := []byte("|wfkuqokj4548366")
        key2 := []byte{0xfb, 0xfe, 0xfb, 0xfe, 0xfb, 0xfe, 0xfb, 0xfe, 0xfb, 0xfe, 0xfb, 0xfe, 0xfb, 0xfe, 0xfb, 0xfe}
        key := []byte{}
        for i, b := range key1 {
                key = append(key, b+key2)
        }
        fmt.Println(string(key))
        block, err := aes.NewCipher(key)
        if err != nil {
                panic(err)
                return
        }
        image3 := make([]byte, len(image2))
        for i := 0; i
关于 Android 调试的一点有趣的事
jadx-gui 和 ida 真的太牛逼了,Android 简单和中等题我根本都没安装过 apk,也没装 Android Studio,直接看 java 或者 so 代码就行。
Android 高级题我就不会了,ida 反编译出错,我自己也不会 arm64 指令集,指令都不认识。
想过利用 https://crates.io/crates/jni-sys 自己实现一下 JavaVM 的 RegisterNatives 接口,放在安卓手机上跑,JNI_OnLoad 确实可以正常调用,但是再往下就麻烦了,动不动就 Segment fault。感觉工作量太大了,就算了。而且就算找到了 RegisterNatives 函数的位置,ida 依然没法反编译,我依然看不懂指令。
这时我已经装了 ndk 和 platform-tools(这两个下载解压就行),但是仍然不想装 Android Studio。
后来看别人的题解才知道有 unidbg 这种东西。估计调试量也不小。

拖到, 下载次数

努力画图   

可以让 IDA 直接导出 DWORD 数组
双击跳到 IDA View 界面,类型改为 DWORD[29](可能还需要让 IDA 识别为数组),按 Shift-E 导出选 initialized C variable
[JavaScript] 纯文本查看 复制代码[
  408, 432, 388, 412, 492, 212, 200, 320, 444, 296, 420, 404, 200, 192, 200,
  204, 288, 388, 448, 448, 484, 312, 404, 476, 356, 404, 388, 456, 500,
]
  .map((x) => x >> 2)
  .map((x) => String.fromCharCode(x))
  .join("");


ida_export.png (113.64 KB, 下载次数: 0)
下载附件
2023-2-8 06:46 上传

nmkj888   

用的很开心    感谢分享
ysy2001   

如果用维吉尼亚密码是不是就稍微会好点
wushengli   

看看,学习一下。
xiaohanjss   

咱也学习下,谢谢分享!
jackyyue_cn   

先收藏学习一下,可惜我都还没入门
Ganlv
OP
  

非常简洁明了,学习了~
nmkj888   


爱飞的猫 发表于 2023-2-8 06:47
可以让 IDA 直接导出 DWORD 数组
双击跳到 IDA View 界面,类型改为 DWORD[29](可能还需要让 IDA 识别为 ...

学到了,感谢教学
您需要登录后才可以回帖 登录 | 立即注册