-
-
[N1CTF2024] ezapk
-
发表于: 2024-11-10 20:07 4220
-
久違的看看安卓題,順便水一篇文章,有任何問題歡迎指出!
拉入jadx,很容易可以定位到關鍵邏輯,經典的加密對比。
加密函數enc
在native層,而且加載了2個so。
嘗試分別將2個so都拉入ida,但都未發現enc
,顯然是動態注冊的。
網上抄的一個frida腳本,用來hook動態注冊的native函數
發現是在libnative1.so!0x1b148
0x1b148
函數如下,重命名成enc
,做了一些奇奇怪怪的操作,等等再分析
在此之前,由於比較好奇另一個so libnative2.so
有什麼用,於是順手查看了.init_array
段,看看有沒有偷偷在做壞事。( 因為在java層沒有發現任何對libnative2.so
函數的調用,只有調用libnative1.so
的,因此合理懷疑對libnative2.so
的操作是在libnative1.so
中進行的,而.init_array
就是一個很好的時機。 )
sub_1B540
是.init_array
段最後一個函數,果然發現了libnative2.so
的字樣。
sub_1B540
一開始先從/proc/self/maps
裡獲取libnative.so
的基址
然後調用sub_1B000
將libnative2.so的一些信息初始化,保存在libnative2_base
sub_1B000
的實現挺像linker加載so的流程中的prelink_image
。
sub_1B540
最後部份如下,大概是將libnative2.so
裡的rand
函數返回值固定為0xE9
。
看完.init_array
後,可以回到enc
函數了( 其實上面的那些東西看不看都沒有所謂,單純是我好奇想看看,純動調其實就能解決這題 )。
動調後會發現,第1個紅框大概是在取libnative2.so
某個函數的offset,然後第2個紅框調用該函數對輸入進行加密( 通過base + offset得到函數的具體地址 )。
一步一步調試完後會發現,總共從libnative2.so
裡取了3個加密函數。
第1個的offset是0x106C
,只是簡單的異或,異或的值是上述分析的0xE9
。
第2個的offset是0x12C0
,一眼RC4。
第3個的offset是0x1AB0
,一眼base64。
最終結果:MysT3r10us_C0d3_2024N1CTF!
這題目挺好的,感覺我以往遇到的題更偏向於算法的部份,而這題對算法分析的要求不高,反而多了一些android逆向實際可能會遇到的東西,挺有意思的。
// com.n1ctf2024.ezapk
function
find_RegisterNatives(params) {
let symbols = Module.enumerateSymbolsSync(
"libart.so"
);
let addrRegisterNatives =
null
;
for
(let i = 0; i < symbols.length; i++) {
let symbol = symbols[i];
//_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
if
(symbol.name.indexOf(
"art"
) >= 0 &&
symbol.name.indexOf(
"JNI"
) >= 0 &&
symbol.name.indexOf(
"RegisterNatives"
) >= 0 &&
symbol.name.indexOf(
"CheckJNI"
) < 0) {
addrRegisterNatives = symbol.address;
console.log(
"RegisterNatives is at "
, symbol.address, symbol.name);
hook_RegisterNatives(addrRegisterNatives)
}
}
}
function
hook_RegisterNatives(addrRegisterNatives) {
if
(addrRegisterNatives !=
null
) {
Interceptor.attach(addrRegisterNatives, {
onEnter:
function
(args) {
console.log(
"[RegisterNatives] method_count:"
, args[3]);
let java_class = args[1];
let class_name = Java.vm.tryGetEnv().getClassName(java_class);
//console.log(class_name);
let methods_ptr = ptr(args[2]);
let method_count = parseInt(args[3]);
for
(let i = 0; i < method_count; i++) {
let name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
let sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
let fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
let name = Memory.readCString(name_ptr);
let sig = Memory.readCString(sig_ptr);
let symbol = DebugSymbol.fromAddress(fnPtr_ptr)
console.log(
"[RegisterNatives] java_class:"
, class_name,
"name:"
, name,
"sig:"
, sig,
"fnPtr:"
, fnPtr_ptr,
" fnOffset:"
, symbol,
" callee:"
, DebugSymbol.fromAddress(
this
.returnAddress));
}
}
});
}
}
setImmediate(find_RegisterNatives);
// com.n1ctf2024.ezapk
function
find_RegisterNatives(params) {
let symbols = Module.enumerateSymbolsSync(
"libart.so"
);
let addrRegisterNatives =
null
;
for
(let i = 0; i < symbols.length; i++) {
let symbol = symbols[i];
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
- [原创] LIAPP手遊保護分析 13470
- [N1CTF2024] ezapk 4221
- [原创] 淺談Cocos2djs逆向 38805
- [求助]wx裡搜尋公眾號不顯示任何結果 2407
- [原创]自實現Linker加載so 27294