初探Harmony逆向之so文件逆向分析篇
最近CTF鸿蒙逆向题出的频率还算高,本篇文章以蜀道山高校公益联赛上的HelloHarmony这题为核心来讲解一下Harmony逆向的so文件逆向分析
附件直接给了个Harmony系统的应用程序安装包.hap文件
直接改成zip进行解压拿到源码文件去反编译看逻辑
.abc文件就是Harmony的源码wen'j
程序反编译
编译工具还是用的jadx-gui-dev-all.jar
https://github.com/ohos-decompiler/abc-decompiler/releases
去Index里面看看
这里应该就是主逻辑了,可以看得出这是一个登录软件,账号直接给出来了
LZSDS
静态分析java层
那就是要逆密码了
我们看一下他获取我输入的密码做了哪些操作
(200 == testNapi.check(newobjrange.encrypt(_lexenv_01.password)) ? 1 : 0
newobjrange实际上是
可以在反编译出来的类里面看见
encrypt里面调用的是transform
transform则是一个魔改的凯撒,对大写字母的偏移是传参进来的5而小写字母则是5+2
那么newobjrange.encrypt(_lexenv_01.password)就分析完了,接下来就是看看testNapi.check()这个函数是做什么的
首先testNapi = import { default as testNapi } from "@normalized:Y&&&libentry.so&";
那么这个check实际上就是libentry.so里面的函数
分析SO文件
so文件在哪了?这里和安卓一样,安装包解压出来有个libs目录,so文件就在libs目录里面
拖入ida进行分析
通过字符串定位到check函数
深入分析函数
密钥扩展里面有两步操作,先是通过WTF::banana(this);初始化Sbox
再通过WTF::bananana(this, a2, a3);把key经过映射关系和或运算给Sbox
接下来分析Sbox和输入的密码进行的加密操作
WTF::heiheihei的传参则是Sbox,输入,存储结果的temp
加密经过8轮迭代,分析一下这8轮迭代做了什么
WTF::blablablablabla(Sbox, temp, i);函数进行的是一个异或操作,我刚开始分析的时候以为这个加密算法只对前8byte数据进行加密看完后面几个函数我就明白了。
WTF::bla(Sbox, temp);这里面则是一个映射操作
WTF::blablabla(Sbox, temp);函数则是对输入进行了一个循环左移的操作,这里面没用到Sbox
循环左移1位
到这里你应该就明白了,为什么不是只对前8byte的数据进行加密了,前8byte的数据经过循环移位会不断的变换位置,所以每一位都会经过异或处理
逆算法
那我们接下来的解密顺序则是
循环右移——>逆Sbox——>Xor
迭代数也要从7开始
Sbox怎么逆了?
Input[i] = Sbox[Input[i]]
加密里面是以Input[i]作为索引在Sbox里去取值的
也就是说索引就是Input[i]
写个Find去遍历索引即可
完整解密
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
void Init_Key(uint8_t* Sbox) {
int i = 0;
for (i = 0; i < 256; ++i) {
Sbox[i] = (167 * i + 173) % 256;
}
}
void GK(uint8_t* Sbox, char* key, int len) {
int i = 0;
for (i = 0; i < 8; ++i) {
uint32_t key_chunk = key[(i + 3) % len] |
(key[(i + 2) % len] << 8) |
(key[(i + 1) % len] << 16) |
(key[i % len] << 24);
*((uint32_t*)Sbox + i + 64) = key_chunk;
}
}
void GetKeyStream(uint8_t* Sbox, char* key, int len) {
Init_Key(Sbox);
GK(Sbox, key, len);
}
// 右移函数
void Right(uint8_t* enc) {
uint8_t temp[40] = { 0 };
int i;
for (i = 0; i < 39; i++) {
temp[i + 1] = enc[i];
}
temp[0] = enc[39];
memcpy(enc, temp, sizeof(temp));
}
int Find(uint8_t enc, uint8_t* Sbox) {
int index = 0;
for (index = 0; index < 256; index++) {
if (enc == Sbox[index]) {
return index;
}
}
return -1;
}
void ReSbox(uint8_t* Sbox, uint8_t* enc) {
int i;
for (i = 0; i < 40; i++) {
enc[i] = Find(enc[i], Sbox);
}
}
void deXor(uint8_t* enc, uint8_t* Sbox, int i) {
*((uint32_t*)enc) ^= *((uint32_t*)Sbox + i + 64);
*((uint32_t*)enc + 1) ^= *((uint32_t*)Sbox + i + 64);
}
void Decrypt(uint8_t* Sbox, uint8_t* enc, int i) {
Right(enc);
ReSbox(Sbox, enc);
deXor(enc, Sbox, i);
}
void CaesarDecrypt(uint8_t* text, int shift) {
int i = 0;
while (text[i] != '\0') {
if (text[i] >= 'A' && text[i] <= 'Z') {
text[i] = ((text[i] - 'A' - shift + 26) % 26) + 'A';
}
else if (text[i] >= 'a' && text[i] <= 'z') {
text[i] = ((text[i] - 'a' - shift-2 + 26) % 26) + 'a';
}
i++;
}
}
int main() {
char key[] = "HelloSDS";
uint8_t Sbox[256] = { 0 };
uint8_t enc[40] = {
0xF6, 0xB0, 0xA6, 0x36, 0x9A, 0xB3, 0x2B, 0xBF, 0x94, 0x54,
0x15, 0x97, 0x93, 0x59, 0xBF, 0x50, 0x4D, 0xBF, 0x0A, 0x59,
0x06, 0xD7, 0x97, 0x50, 0xD6, 0x59, 0x54, 0xD7, 0xCF, 0x06,
0x5D, 0x20, 0x1D, 0x5A, 0x22, 0xEE, 0x99, 0x1F, 0xE1, 0x18
};
int i;
int len = strlen(key);
GetKeyStream(Sbox, key, len);
for (i = 7; i >= 0; i--) {
Decrypt(Sbox, enc, i);
}
CaesarDecrypt(enc, 5);
puts((char*)enc);
return 0;
}
//LZSDS{y0u_4r3_4_m4573r_0f_cryp706r4phy}
去用程序验证一下
依旧是使用DevEco Studio去模拟Harmony
把.hap文件直接拖进去即可安装
验证成功!
感谢师傅们的观看!
- HelloHarmony.zip 下载