搜狗搜索-公众号文章列表unidbg逆向
Java层
从抓包结果看,参数和返回结果都经过加密,而且参数名都是极其简单的单个字符串,不太好入手,尝试从请求的url入手,在jadx搜索v2.get
进入看看
疑似加密和解密的函数
可以看到最终是调用了ScoreTools
这个so里面的native函数,接下来使用frida hook看看。
function hook_encrypt() {
var ScEncryptWall = Java.use('com.sogou.scoretools.ScEncryptWall');
ScEncryptWall.encrypt.implementation = function (a, b, c) {
console.log('encrypt.a:', a);
console.log('encrypt.b:', b);
console.log('encrypt.c:', c);
var res = this.encrypt(a, b, c);
console.log('encrypt.res:', res);
return res;
}
}
Java.perform(function () {
hook_encrypt();
})
so层
ida打开libSCoreTools.so
,函数窗口搜索java
,可以看出是静态注册的,接下来用unidbg调用encrypt
函数
unidbg逆向
package com.sogou;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.hook.hookzz.*;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.sun.jna.Pointer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Sogou extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
public static String pkgName = "com.sogou.activity.src";
public static String apkPath = "unidbg-android/src/test/java/com/sogou/sogou7.9.6.6.apk";
public static String soPath = "unidbg-android/src/test/java/com/sogou/libSCoreTools.so";
public Sogou() {
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
vm = emulator.createDalvikVM(new File(apkPath));
vm.setVerbose(true);
DalvikModule dm = vm.loadLibrary(new File(soPath), true);
vm.setJni(this);
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
}
public void call_encrypt() {
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
list.add(0);
list.add(vm.addLocalObject(new StringObject(vm, "http://app.weixin.sogou.com/api/searchapp")));
list.add(vm.addLocalObject(new StringObject(vm, "type=2&ie=utf8&page=2&query=Python&select_count=0&usip=")));
list.add(vm.addLocalObject(new StringObject(vm, "")));
Number number = module.callFunction(emulator, 0x9ca0+1, list.toArray())[0];
System.out.println("Result:" + vm.getObject(number.intValue()).getValue().toString());
}
public static void main(String[] args) {
Sogou test = new Sogou();
test.call_encrypt();
}
}
运行之后发现,跑完了整个流程,但是没有结果。不过在java代码里面就发现了有个init函数,也许我们要先调用一下这个函数。
public void call_init() {
DvmClass Context = vm.resolveClass("android/content/Context");
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
list.add(0);
list.add(vm.addLocalObject(Context.newObject(null)));
Number number = module.callFunction(emulator, 0x9564+1, list.toArray())[0];
System.out.println("init:" + number.intValue());
}
public static void main(String[] args) {
Sogou test = new Sogou();
test.call_init();
test.call_encrypt();
}
结果出来了,同样的参数运行多次,我们发现每次的结果都不一样,说明算法的输入可能还有随机数或时间戳的参与。
完整代码
package com.sogou;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.hook.hookzz.*;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.sun.jna.Pointer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Sogou extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
public static String pkgName = "com.sogou.activity.src";
public static String apkPath = "unidbg-android/src/test/java/com/sogou/sogou7.9.6.6.apk";
public static String soPath = "unidbg-android/src/test/java/com/sogou/libSCoreTools.so";
public Sogou() {
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
vm = emulator.createDalvikVM(new File(apkPath));
vm.setVerbose(true);
DalvikModule dm = vm.loadLibrary(new File(soPath), true);
vm.setJni(this);
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
}
public void call_init() {
DvmClass Context = vm.resolveClass("android/content/Context");
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
list.add(0);
list.add(vm.addLocalObject(Context.newObject(null)));
Number number = module.callFunction(emulator, 0x9564+1, list.toArray())[0];
System.out.println("init:" + number.intValue());
}
public void call_encrypt() {
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
list.add(0);
list.add(vm.addLocalObject(new StringObject(vm, "http://app.weixin.sogou.com/api/searchapp")));
list.add(vm.addLocalObject(new StringObject(vm, "type=2&ie=utf8&page=2&query=Python&select_count=0&usip=")));
list.add(vm.addLocalObject(new StringObject(vm, "")));
Number number = module.callFunction(emulator, 0x9ca0+1, list.toArray())[0];
System.out.println("Result:" + vm.getObject(number.intValue()).getValue().toString());
}
public static void main(String[] args) {
Sogou test = new Sogou();
test.call_init();
test.call_encrypt();
}
}
代码仅供把玩。