feat(huya): unidbg encode_aes 探针上线 + 64B钥材料发现(AES变体非标)
- AesProbe.java: 直接调用 encode_aes, 权威差分源 (已知输入输出已记录) - KeyExpansion 以16B步长读钥 → 64B材料; 标准AES对照 b1e3abcc≠ba3fb8f1 证变体 - docs §11.16
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
package hydev;
|
||||
|
||||
import com.github.unidbg.AndroidEmulator;
|
||||
import com.github.unidbg.Module;
|
||||
import com.github.unidbg.arm.backend.BackendFactory;
|
||||
import com.github.unidbg.arm.backend.DynarmicFactory;
|
||||
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
|
||||
import com.github.unidbg.linux.android.AndroidResolver;
|
||||
import com.github.unidbg.linux.android.dvm.DalvikModule;
|
||||
import com.github.unidbg.linux.android.dvm.StringObject;
|
||||
import com.github.unidbg.linux.android.dvm.VM;
|
||||
import com.github.unidbg.memory.Memory;
|
||||
import com.github.unidbg.pointer.UnidbgPointer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* unidbg 探针: 直接调用 libudbauthunify.so 的 encode_aes@0x330218 (IN, KEY, OUT)
|
||||
* 与 UdbAESUtil 全家, 用可控输入差分出 32hex-HDID32 的 AES 算法细节.
|
||||
*
|
||||
* std::string ABI (NDK libc++):
|
||||
* short: [0]=len<<1 (LSB=0), data@[1..24]
|
||||
* long : [0..7]=cap(LSB=1), [8..15]=size, [16..23]=data-ptr
|
||||
*/
|
||||
public class AesProbe {
|
||||
|
||||
static final Map<String, String> PREFS = new LinkedHashMap<>();
|
||||
static {
|
||||
PREFS.put("hydeviceid_config", "2AQq9oUCCZ8MgS1qhJHFp+U7vBdmTBVkH8WlXondx64IE+kvc65rHJtuTazmCLT0Z7FYQEVuosfMmclJOeQrI7PLlAhhZYU5dXoYCKQJ7/ze1y5V6DvozlZZUQLG9jgoNJ4kdEyEi3QQavTQGdiokQ==");
|
||||
}
|
||||
|
||||
private final AndroidEmulator emulator;
|
||||
private final VM vm;
|
||||
private final Module module;
|
||||
|
||||
AesProbe(String soPath) throws Exception {
|
||||
BackendFactory backend = new DynarmicFactory(true);
|
||||
emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.duowan.kiwi").addBackendFactory(backend).build();
|
||||
Memory memory = emulator.getMemory();
|
||||
memory.setLibraryResolver(new AndroidResolver(23));
|
||||
vm = emulator.createDalvikVM();
|
||||
vm.setJni(new com.github.unidbg.linux.android.dvm.AbstractJni() {});
|
||||
vm.setVerbose(false);
|
||||
DalvikModule dm = vm.loadLibrary(new File(soPath), false);
|
||||
dm.callJNI_OnLoad(emulator);
|
||||
module = dm.getModule();
|
||||
System.out.println("[*] lib loaded base=0x" + Long.toHexString(module.base));
|
||||
}
|
||||
|
||||
// 写一个 NDK-libc++ std::string (short 形式: len<=22 走 inline)
|
||||
UnidbgPointer writeStdString(String s) {
|
||||
Memory mem = emulator.getMemory();
|
||||
byte[] data = s.getBytes();
|
||||
int len = data.length;
|
||||
UnidbgPointer p;
|
||||
if (len <= 22) {
|
||||
// short: [0] = len<<1, data @1
|
||||
p = mem.malloc(24, false).getPointer();
|
||||
byte[] buf = new byte[24];
|
||||
buf[0] = (byte) (len << 1);
|
||||
System.arraycopy(data, 0, buf, 1, len);
|
||||
p.write(0, buf, 0, buf.length);
|
||||
} else {
|
||||
// long: [0..7]=cap(LSB=1 = 0xffff...f), [8..15]=size, [16..23]=ptr
|
||||
UnidbgPointer heap = mem.malloc(len + 1, false).getPointer();
|
||||
heap.write(0, data, 0, len);
|
||||
heap.write(len, new byte[]{0}, 0, 1);
|
||||
p = mem.malloc(24, false).getPointer();
|
||||
byte[] cap = new byte[8]; Arrays.fill(cap, (byte) 0xff);
|
||||
p.write(0, cap, 0, 8);
|
||||
p.write(8, new byte[]{(byte) (len & 0xff), (byte) (len >> 8), 0, 0, 0, 0, 0, 0}, 0, 8);
|
||||
byte[] ptrBytes = new byte[8];
|
||||
long pv = UnidbgPointer.nativeValue(heap);
|
||||
for (int i = 0; i < 8; i++) ptrBytes[i] = (byte) (pv >> (8 * i));
|
||||
p.write(16, ptrBytes, 0, 8);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
String readStdString(UnidbgPointer p) {
|
||||
byte[] one = new byte[1];
|
||||
p.read(0, one, 0, 1);
|
||||
int first = one[0] & 0xff;
|
||||
if ((first & 1) == 0) {
|
||||
int len = first >> 1;
|
||||
byte[] dat = new byte[len];
|
||||
p.read(1, dat, 0, len);
|
||||
return new String(dat, java.nio.charset.StandardCharsets.ISO_8859_1);
|
||||
} else {
|
||||
long size = 0;
|
||||
byte[] szb = new byte[8];
|
||||
p.read(8, szb, 0, 8);
|
||||
for (int i = 0; i < 8; i++) size |= ((long) (szb[i] & 0xff)) << (8 * i);
|
||||
byte[] ptrb = new byte[8];
|
||||
p.read(16, ptrb, 0, 8);
|
||||
long pv = 0;
|
||||
for (int i = 0; i < 8; i++) pv |= ((long) (ptrb[i] & 0xff)) << (8 * i);
|
||||
UnidbgPointer data = UnidbgPointer.pointer(this.emulator, pv);
|
||||
byte[] dat2 = new byte[(int) size];
|
||||
data.read(0, dat2, 0, (int) size);
|
||||
return new String(dat2, java.nio.charset.StandardCharsets.ISO_8859_1);
|
||||
}
|
||||
}
|
||||
|
||||
String callEncodeAes(String in, String key) {
|
||||
UnidbgPointer pin = writeStdString(in);
|
||||
UnidbgPointer pkey = writeStdString(key);
|
||||
UnidbgPointer pout = writeStdString("");
|
||||
long base = module.base;
|
||||
Number retN = module.callFunction(emulator, 0x330218L, UnidbgPointer.nativeValue(pin), UnidbgPointer.nativeValue(pkey), UnidbgPointer.nativeValue(pout));
|
||||
long ret = retN == null ? 0 : retN.longValue();
|
||||
String out = readStdString(pout);
|
||||
System.out.println("[encode_aes] in=" + in + " key=" + key + " -> out=" + out + " hex=" + toHex(out) + " (ret=" + ret + ")");
|
||||
return out;
|
||||
}
|
||||
|
||||
static String toHex(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : s.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1)) sb.append(String.format("%02x", b));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String so = args.length > 0 ? args[0] : "so/libudbauthunify_merged.so";
|
||||
AesProbe p = new AesProbe(so);
|
||||
// 基准: 已知 16B 明文 + 24B 钥
|
||||
// 64B 钥材料测试 (KeyExpansion 以 16B 步长读!!)
|
||||
String k64_zmhav = "ZMHAVPRaxJ3MtXDjduUnXAKQ" + "\0".repeat(0);
|
||||
k64_zmhav = String.format("%-64s", "ZMHAVPRaxJ3MtXDjduUnXAKQ").replace(' ', '\0');
|
||||
String k64_ow = String.format("%-64s", "owNMiaCgcHmqoTr3iRamFuHj").replace(' ', '\0');
|
||||
String k64_cfg0 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
p.callEncodeAes("0123456789abcdef", k64_zmhav);
|
||||
p.callEncodeAes("0123456789abcdef", k64_ow);
|
||||
p.callEncodeAes("0123456789abcdef", k64_cfg0);
|
||||
p.callEncodeAes("1e8bdf7d4f7a01d3", k64_zmhav);
|
||||
p.callEncodeAes("1e8bdf7d4f7a01d3", k64_cfg0);
|
||||
p.emulator.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user