某手__NS_sig3:明文-> hmacsha256后得到32字节的加密值->aes加密后得到32字节的密文->crc32校验值得到4字节的校验值,逆向过程颇为复杂,就不发分析过程了,直接发关键位置和纯算代码,需要的自取参考。java层关键调用:

//
// Decompiled by Jadx - 849ms
//
package com.kuaishou.android.security.internal.plugin;
import com.kuaishou.android.security.base.exception.KSException;
import com.kuaishou.android.security.base.perf.b;
import com.kuaishou.android.security.base.perf.d;
import com.kuaishou.android.security.internal.dispatch.JNICLibrary;
import com.kwai.robust.PatchProxy;
import com.kwai.robust.PatchProxyResult;
import java.util.Locale;
public class k implements e {
public Object a(int i, Object... objArr) throws KSException {
boolean z;
Object applyTwoRefs;
if (PatchProxy.isSupport(k.class) && (applyTwoRefs = PatchProxy.applyTwoRefs(Integer.valueOf(i), objArr, this, k.class, "1")) != PatchProxyResult.class) {
return applyTwoRefs;
}
Object obj = null;
try {
return JNICLibrary.doCommandNative(i, objArr);
} catch (Throwable th) {
try {
obj = JNICLibrary.doCommandNative(i, objArr);
z = false;
} catch (Throwable th2) {
d.a(d.b.f, String.format(Locale.getDefault(), "retry exception1[%s] exception2[%s] p[%d]", th.getMessage(), th2.getMessage(), Integer.valueOf(i)), b.h);
z = true;
}
if (!z) {
d.a(d.b.a, String.format(Locale.getDefault(), "dc exception[%s] p[%d]", th.getMessage(), Integer.valueOf(i)), b.i);
}
return obj;
}
}
}
unidbg hook:
```java
package com.ks;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.IOResolver;
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.linux.android.dvm.api.AssetManager;
import com.github.unidbg.linux.android.dvm.array.ArrayObject;
import com.github.unidbg.linux.android.dvm.wrapper.DvmBoolean;
import com.github.unidbg.linux.android.dvm.wrapper.DvmInteger;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.virtualmodule.android.AndroidModule;
import com.github.unidbg.virtualmodule.android.JniGraphics;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
public class ks2 extends AbstractJni implements IOResolver{
@Override
public FileResult resolve(Emulator emulator, String pathname, int oflags) {
System.out.println("file open:"+pathname);
return null;
}
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
ks2(){
emulator = AndroidEmulatorBuilder.for64Bit().build();
// 获取模拟器的内存操作接口
final Memory memory = emulator.getMemory();
// 设置系统类库解析
memory.setLibraryResolver(new AndroidResolver(23));
// 创建Android虚拟机,传入APK,Unidbg可以替我们做部分签名校验的工作
vm = emulator.createDalvikVM(new File("unidbg-android/apks/ks/ks11.420.30984.apk"));
// 设置JNI
vm.setJni(this);
// 打印日志
vm.setVerbose(true);
new JniGraphics(emulator, vm).register(memory);
new AndroidModule(emulator, vm).register(memory);
emulator.getSyscallHandler().addIOResolver(this); //重定向io
// 加载目标SO
DalvikModule dm = vm.loadLibrary("kwsgmain", true);
//DalvikModule dm = vm.loadLibrary(new File("unidbg-android/apks/ks/libkwsgmain.so"), true);
//获取本SO模块的句柄,后续需要用它
module = dm.getModule();
// 调用JNI OnLoad
dm.callJNI_OnLoad(emulator);
};
public void callByAddress(){
List<Object> list = new ArrayList<>(4);
list.add(vm.getJNIEnv()); // 第⼀个参数是env
DvmObject<?> thiz = vm.resolveClass("com/kuaishou/android/security/internal/dispatch/JNICLibrary").newObject(null);
list.add(vm.addLocalObject(thiz)); // 第⼆个参数,实例⽅法是jobject,静态⽅法是jclass,直接填0,⼀般⽤不到。
DvmObject<?> context = vm.resolveClass("com/yxcorp/gifshow/App").newObject(null); // context
vm.addLocalObject(context);
list.add(10412); //参数1
StringObject appkey = new StringObject(vm, "d7b7d042-d4f2-4012-be60-d97ff2429c17"); // SO⽂件有校验
vm.addLocalObject(appkey);
DvmInteger intergetobj = DvmInteger.valueOf(vm, 0);
vm.addLocalObject(intergetobj);
list.add(vm.addLocalObject(new ArrayObject(intergetobj, appkey, intergetobj, intergetobj, context, intergetobj, intergetobj)));
// 直接通过地址调⽤
Number numbers = module.callFunction(emulator, 0x41680, list.toArray());
System.out.println("numbers:" + numbers);
DvmObject<?> object = vm.getObject(numbers.intValue());
String result = (String) object.getValue();
System.out.println("result:" + result);
};
@Override
public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "com/yxcorp/gifshow/App->getPackageCodePath()Ljava/lang/String;": {
return new StringObject(vm, "/data/app/com.smile.gifmaker-q14Fo0PSb77vTIOM1-iEqQ==/base.apk");
}
case "com/yxcorp/gifshow/App->getAssets()Landroid/content/res/AssetManager;": {
return new AssetManager(vm, signature);
}
case "com/yxcorp/gifshow/App->getPackageName()Ljava/lang/String;": {
return new StringObject(vm, "com.smile.gifmaker");
}
case "com/yxcorp/gifshow/App->getPackageManager()Landroid/content/pm/PackageManager;": {
DvmClass clazz = vm.resolveClass("android/content/pm/PackageManager");
return clazz.newObject(signature);
}
}
return super.callObjectMethodV(vm, dvmObject, signature, vaList);
}
@Override
public boolean callBooleanMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "java/lang/Boolean->booleanValue()Z":
DvmBoolean dvmBoolean = (DvmBoolean) dvmObject;
return dvmBoolean.getValue();
}
return super.callBooleanMethodV(vm, dvmObject, signature, vaList);
}
@Override
public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
switch (signature) {
case "com/kuaishou/android/security/internal/common/ExceptionProxy->getProcessName(Landroid/content/Context;)Ljava/lang/String;":
return new StringObject(vm, "com.smile.gifmaker");
case "com/meituan/android/common/mtguard/NBridge->getSecName()Ljava/lang/String;":
return new StringObject(vm, "ppd_com.sankuai.meituan.xbt");
case "com/meituan/android/common/mtguard/NBridge->getAppContext()Landroid/content/Context;":
return vm.resolveClass("android/content/Context").newObject(null);
case "com/meituan/android/common/mtguard/NBridge->getMtgVN()Ljava/lang/String;":
return new StringObject(vm, "4.4.7.3");
case "com/meituan/android/common/mtguard/NBridge->getDfpId()Ljava/lang/String;":
return new StringObject(vm, "");
}
return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);
}
@Override
public void callStaticVoidMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
switch (signature){
case "com/kuaishou/android/security/internal/common/ExceptionProxy->nativeReport(ILjava/lang/String;)V":{
return;
}
}
super.callStaticVoidMethodV(vm, dvmClass, signature, vaList);
}
public String get_NS_sig3() throws FileNotFoundException {
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv()); // 第⼀个参数是env
DvmObject<?> thiz = vm.resolveClass("com/kuaishou/android/security/internal/dispatch/JNICLibrary").newObject(null);
list.add(vm.addLocalObject(thiz)); // 第⼆个参数,实例⽅法是jobject,静态⽅法是jclass,直接填0,⼀般⽤不到。
DvmObject<?> context = vm.resolveClass("com/yxcorp/gifshow/App").newObject(null); // context
vm.addLocalObject(context);
list.add(10418); //参数1
StringObject urlObj = new StringObject(vm, "doubao");
vm.addLocalObject(urlObj);
ArrayObject arrayObject = new ArrayObject(urlObj);
StringObject appkey = new StringObject(vm, "d7b7d042-d4f2-4012-be60-d97ff2429c17");
vm.addLocalObject(appkey);
DvmInteger intergetobj = DvmInteger.valueOf(vm, -1);
vm.addLocalObject(intergetobj);
DvmBoolean boolobj = DvmBoolean.valueOf(vm, false);
vm.addLocalObject(boolobj);
StringObject appkey2 = new StringObject(vm, "7e46b28a-8c93-4940-8238-4c60e64e3c81");
vm.addLocalObject(appkey2);
list.add(vm.addLocalObject(new ArrayObject(arrayObject, appkey, intergetobj, boolobj, context, null, boolobj, appkey2)));
Number numbers = module.callFunction(emulator, 0x41680, list.toArray());
System.out.println("numbers:" + numbers);
DvmObject<?> object = vm.getObject(numbers.intValue());
String result = (String) object.getValue();
System.out.println("result:" + result);
return result;
}
public static void main(String[] args) throws FileNotFoundException {
ks2 ks = new ks2();
ks.callByAddress();
ks.get_NS_sig3();
}
}
```
纯算:

调用:
``` python
url3 = "https://api3.XXapisrv.com/rest/lightks/n/photo/playAuth/v1"
payload3 = {
"photoId": f"{photo_id}",
"cs": "false",
"client_key": "3c2cd3f3",
"os": "android",
}
params_str3 = sig_1.sort_params(params2, payload3)
sig_str3 = sig_1.make_sig(params_str3)
NS_sig3_str3 = sig_3.make_sig3(f"/rest/lightks/n/photo/playAuth/v1{sig_str3}")
params2["sig"] = sig_str3
params2["__NS_sig3"] = NS_sig3_str3
提醒:仅供技术交流,纯算中故意写了一个非常明显的错误,稍微分析过so文件之后就可以知晓的错误,避免直接拿来干坏事。。。
原文链接:http://www.itawp.com/607.html,转载请注明出处。
评论0