首页
社区
课程
招聘
[原创]某咖啡(二)sign参数逆向分析
发表于: 2025-10-7 20:07 3961

[原创]某咖啡(二)sign参数逆向分析

2025-10-7 20:07
3961

上文中我们分析了参数q,这里我们继续来看看sign 我们可以通过q参数的堆栈或者getbyte,hasmap的hook得到

最终跟到a方法 调用md5_crypt 方法 hook一下传参可以得到结果 找到加密点后 写个unidbg调用跑一下

可以看到md5_crypt函数的信息打印出来了 我们去到0x43bbc 处 就是我们运算sign的方法 也有ollvm代码不算多 总共发现2个方法 sub_4559C sub_4095C

我们先改下JNIEnv 让他正确识别一些方法

代码中就出现了2个方法 那我们先hook下 4559C函数 可以看到java传过来的a5 也就是我们u7Su25kSE9PxcTgQZkRgL0kJ+lDaV2IQcqdsfGGuNDs= 这个值 被传进了4559C 跑下hook打印下入参返回

hook 得到入参是 bbb4aedb991213d3f17138106644602f4909fa50da57621072a76c7c61ae343b hex转下也就是我们的u7Su25kSE9PxcTgQZkRgL0kJ+lDaV2IQcqdsfGGuNDs= 这个值 得到 ooL1Bqoa8lF6ZE54

继续看 sub_4095C 有三个参数 hook看看 第一个参数是helloooL1Bqoa8lF6ZE54 也就是 我们的传参1 加上函数4559C 运行传参2 得到的结果拼接 4095C 运行得到结果与md5_crypt 函数运行结果一致 那么继续进入4095C 看啊看

进入后 代码不算多 跟踪我们入参a1 发现被传入41084 方法 由前方代码可得知a1是入参 a2是长度 那我们hook看下返回时第三个参数

hook 结果可以看出 41084函数 就是一个md5算法 但是与我们结果不一样说明 md5的结果 继续做了处理

方便分析 ida 给41084 rename下 md5 记录下 继续ida分析下 发先有几个函数有点可疑,先看4108C 发现也是调用了3D1F4

我们发现 它调用了3D1F4方法 每次处理md5加密结果的4字节 然后运算的结果经过 sub_4109C 取绝对值或者经过与0比较取本身或取反的操作取绝对值 格式化输出后通过strcat 拼接得到最后结果 那么核心就是函数3D1F4

来到3D1F4,代码虽然少但是看不出啥玩意 debugger看一下先

断点后可以看见传参第一个x1 是我们md5的结果,第二个参数就是x1=0x0 也就是 v17 = sub_3D1F4(v32, 0LL);运行了

然后我们blr断点返回 然后按c运行 查看 在这里我们能发现一个关键的地方 观察x0 可以发现是 x0=0xd3f10f0f(-739176689) 其中 739176689 正好是我们md5_crypt 结果的前面一部分 继续debugger 他会运行v19 = sub_3D1F4(v32, 4LL);

我们看此时返回的结果 x0=0x64ae26b6 0x64ae26b6 转十进制正好是1689134774 是加密结果的第二部分 继续

得到结果 x0=0xb095c92 x0=0x172e2950 转换后 依次为185162898 388901200

对应结果 7391766891689134774185162898388901200 185162898388901200

经过断点查看我们发现如果是负值 结果就会变化 如果是正值结果就是MD5传入的字节部分转十进制的结果,到此我们还是不能分析出这玩意到底咋搞的 在运行函数时 trace一下汇编看看

我们只看一次就行了 搜md5传参加密结果 d3f10f0f64ae26b60b095c92172e2950前4个字节 d3f10f0f 在此处 我们看这

这三行汇编 具体实现为

到这里基本上就能理解了,对MD5的结果传入函数比较 然后根据情况取反操作 写个python 实现下

首先对传参md5 得到 9f8b2056b6cb87149b196da5b305059a 然后 运算得到 结果与unidbg结果对比一致 完结

此案例总体来说还是很简单的,用来练习Unidbg刚刚好。虽然有ollvm,但是 代码量不算大,还是阔以看着搞。

public void md5_crypt(){
        DvmClass CryptoHelper = vm.resolveClass("com/luckincoffee/safeboxlib/CryptoHelper");
        byte[] bytes = "hello".getBytes();
        String a2  = "u7Su25kSE9PxcTgQZkRgL0kJ+lDaV2IQcqdsfGGuNDs=" ;
        byte[] bytes2 = Base64.getDecoder().decode(a2.replace('-', '+').replace('_', '/').getBytes());
        ByteArray reval = CryptoHelper.callStaticJniMethodObject(emulator, "md5_crypt([BI[B)[B",  bytes,1,bytes2);
        System.out.println("md5_crypt:" + new String(reval.getValue()));
    }
    =================================================
    JNIEnv->FindClass(com/luckincoffee/safeboxlib/CryptoHelper) was called from RX@0x400450c8[libcryptoDD.so]0x450c8
JNIEnv->RegisterNatives(com/luckincoffee/safeboxlib/CryptoHelper, RW@0x4004bce0[libcryptoDD.so]0x4bce0, 3) was called from RX@0x40044968[libcryptoDD.so]0x44968
RegisterNative(com/luckincoffee/safeboxlib/CryptoHelper, localAESWork([BI[B)[B, RX@0x40041ed8[libcryptoDD.so]0x41ed8)
RegisterNative(com/luckincoffee/safeboxlib/CryptoHelper, localConnectWork([B[B)[B, RX@0x40041bb0[libcryptoDD.so]0x41bb0)
RegisterNative(com/luckincoffee/safeboxlib/CryptoHelper, md5_crypt([BI[B)[B, RX@0x40043bbc[libcryptoDD.so]0x43bbc)
Find native function Java_com_luckincoffee_safeboxlib_CryptoHelper_md5_1crypt => RX@0x40043bbc[libcryptoDD.so]0x43bbc
JNIEnv->GetArrayLength([B@6cd8737 => 5) was called from RX@0x40043c18[libcryptoDD.so]0x43c18
JNIEnv->GetArrayLength([B@22f71333 => 32) was called from RX@0x40041288[libcryptoDD.so]0x41288
JNIEnv->NewByteArray(16) was called from RX@0x400415a4[libcryptoDD.so]0x415a4
JNIEnv->SetByteArrayRegion([B@6aaa5eb0, 0, 16, RW@0x40398080) was called from RX@0x400419d8[libcryptoDD.so]0x419d8
JNIEnv->GetArrayLength([B@6aaa5eb0 => 16) was called from RX@0x40044244[libcryptoDD.so]0x44244
JNIEnv->NewByteArray(37) was called from RX@0x400442b0[libcryptoDD.so]0x442b0
JNIEnv->SetByteArrayRegion([B@1a407d53, 0, 37, RW@0x40393060) was called from RX@0x400441a8[libcryptoDD.so]0x441a8
md5_crypt:7391766891689134774185162898388901200
     
     
    
public void md5_crypt(){
        DvmClass CryptoHelper = vm.resolveClass("com/luckincoffee/safeboxlib/CryptoHelper");
        byte[] bytes = "hello".getBytes();
        String a2  = "u7Su25kSE9PxcTgQZkRgL0kJ+lDaV2IQcqdsfGGuNDs=" ;
        byte[] bytes2 = Base64.getDecoder().decode(a2.replace('-', '+').replace('_', '/').getBytes());
        ByteArray reval = CryptoHelper.callStaticJniMethodObject(emulator, "md5_crypt([BI[B)[B",  bytes,1,bytes2);
        System.out.println("md5_crypt:" + new String(reval.getValue()));
    }
    =================================================
    JNIEnv->FindClass(com/luckincoffee/safeboxlib/CryptoHelper) was called from RX@0x400450c8[libcryptoDD.so]0x450c8
JNIEnv->RegisterNatives(com/luckincoffee/safeboxlib/CryptoHelper, RW@0x4004bce0[libcryptoDD.so]0x4bce0, 3) was called from RX@0x40044968[libcryptoDD.so]0x44968
RegisterNative(com/luckincoffee/safeboxlib/CryptoHelper, localAESWork([BI[B)[B, RX@0x40041ed8[libcryptoDD.so]0x41ed8)
RegisterNative(com/luckincoffee/safeboxlib/CryptoHelper, localConnectWork([B[B)[B, RX@0x40041bb0[libcryptoDD.so]0x41bb0)
RegisterNative(com/luckincoffee/safeboxlib/CryptoHelper, md5_crypt([BI[B)[B, RX@0x40043bbc[libcryptoDD.so]0x43bbc)
Find native function Java_com_luckincoffee_safeboxlib_CryptoHelper_md5_1crypt => RX@0x40043bbc[libcryptoDD.so]0x43bbc
JNIEnv->GetArrayLength([B@6cd8737 => 5) was called from RX@0x40043c18[libcryptoDD.so]0x43c18
JNIEnv->GetArrayLength([B@22f71333 => 32) was called from RX@0x40041288[libcryptoDD.so]0x41288
JNIEnv->NewByteArray(16) was called from RX@0x400415a4[libcryptoDD.so]0x415a4
JNIEnv->SetByteArrayRegion([B@6aaa5eb0, 0, 16, RW@0x40398080) was called from RX@0x400419d8[libcryptoDD.so]0x419d8
JNIEnv->GetArrayLength([B@6aaa5eb0 => 16) was called from RX@0x40044244[libcryptoDD.so]0x44244
JNIEnv->NewByteArray(37) was called from RX@0x400442b0[libcryptoDD.so]0x442b0
JNIEnv->SetByteArrayRegion([B@1a407d53, 0, 37, RW@0x40393060) was called from RX@0x400441a8[libcryptoDD.so]0x441a8
md5_crypt:7391766891689134774185162898388901200
     
     
    
public void HookByConsoleDebugger(){
      emulator.attach().addBreakPoint(module.base + 0x4559C, new BreakPointCallback() {
          @Override
          public boolean onHit(Emulator<?> emulator, long address) {
              RegisterContext context = emulator.getContext();
              UnidbgPointer input = context.getPointerArg(1);
              DvmObject<?> dvmbytes = vm.getObject(input.toIntPeer());
              byte[] result = (byte[]) dvmbytes.getValue();
              System.out.println("传入数据: " + bytesTohexString(result));
              emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                  @Override
                  public boolean onHit(Emulator<?> emulator, long address) {
                      RegisterContext returnContext = emulator.getContext();
                      UnidbgPointer v12Value = returnContext.getPointerArg(0);
                      DvmObject<?> v12Obj = vm.getObject(v12Value.toIntPeer());
                      byte[] v12Data = (byte[]) v12Obj.getValue();
                      System.out.println("结果: " + new String(v12Data));
                      return true;
                  }
              });
              return true;
          }
      });
  }
public void HookByConsoleDebugger(){
      emulator.attach().addBreakPoint(module.base + 0x4559C, new BreakPointCallback() {
          @Override
          public boolean onHit(Emulator<?> emulator, long address) {
              RegisterContext context = emulator.getContext();
              UnidbgPointer input = context.getPointerArg(1);
              DvmObject<?> dvmbytes = vm.getObject(input.toIntPeer());
              byte[] result = (byte[]) dvmbytes.getValue();
              System.out.println("传入数据: " + bytesTohexString(result));
              emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                  @Override
                  public boolean onHit(Emulator<?> emulator, long address) {
                      RegisterContext returnContext = emulator.getContext();
                      UnidbgPointer v12Value = returnContext.getPointerArg(0);
                      DvmObject<?> v12Obj = vm.getObject(v12Value.toIntPeer());
                      byte[] v12Data = (byte[]) v12Obj.getValue();
                      System.out.println("结果: " + new String(v12Data));
                      return true;
                  }
              });
              return true;
          }
      });
  }
public void HookByConsoleDebugger1(){
    emulator.attach().addBreakPoint(module.base + 0x4095C, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            RegisterContext context = emulator.getContext();
            UnidbgPointer input = context.getPointerArg(0);
            UnidbgPointer output = context.getPointerArg(2);
            System.out.println("传入数据: " + input.getString(0));
            emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                @Override
                public boolean onHit(Emulator<?> emulator, long address) {
                    byte[] v27Data = output.getPointer(0).getByteArray(0,37);
                    System.out.println("结果: " + new String(v27Data));
                    return true;
                }
            });
            return true;
        }
    });
}
public void HookByConsoleDebugger1(){
    emulator.attach().addBreakPoint(module.base + 0x4095C, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            RegisterContext context = emulator.getContext();
            UnidbgPointer input = context.getPointerArg(0);
            UnidbgPointer output = context.getPointerArg(2);
            System.out.println("传入数据: " + input.getString(0));
            emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                @Override
                public boolean onHit(Emulator<?> emulator, long address) {
                    byte[] v27Data = output.getPointer(0).getByteArray(0,37);
                    System.out.println("结果: " + new String(v27Data));
                    return true;
                }
            });
            return true;
        }
    });
}
public void HookByConsoleDebugger2(){
     emulator.attach().addBreakPoint(module.base + 0x41084, new BreakPointCallback() {
         @Override
         public boolean onHit(Emulator<?> emulator, long address) {
             RegisterContext context = emulator.getContext();
             UnidbgPointer input = context.getPointerArg(0);
             UnidbgPointer output = context.getPointerArg(2);
             System.out.println("传入数据: " + input.getString(0));
             emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                 @Override
                 public boolean onHit(Emulator<?> emulator, long address) {
                     Inspector.inspect(output.getByteArray(0, 16), "0x41084 arg3");
                     return true;
                 }
             });
             return true;
         }
     });
 }
public void HookByConsoleDebugger2(){
     emulator.attach().addBreakPoint(module.base + 0x41084, new BreakPointCallback() {
         @Override
         public boolean onHit(Emulator<?> emulator, long address) {
             RegisterContext context = emulator.getContext();
             UnidbgPointer input = context.getPointerArg(0);
             UnidbgPointer output = context.getPointerArg(2);
             System.out.println("传入数据: " + input.getString(0));
             emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                 @Override
                 public boolean onHit(Emulator<?> emulator, long address) {
                     Inspector.inspect(output.getByteArray(0, 16), "0x41084 arg3");
                     return true;
                 }
             });
             return true;
         }
     });
 }
// attributes: thunk
__int64 __fastcall sub_4108C(__int64 a1, __int64 a2)
{
  return sub_3D1F4(a1, a2);
}
 
 
__int64 __fastcall sub_4109C(__int64 result)
{
  if ( result >= 0 )
    return result;
  else
    return -result;
}
// attributes: thunk
__int64 __fastcall sub_4108C(__int64 a1, __int64 a2)
{
  return sub_3D1F4(a1, a2);
}
 
 
__int64 __fastcall sub_4109C(__int64 result)
{
  if ( result >= 0 )
    return result;
  else
    return -result;
}
v17 = sub_3D1F4(v32, 0LL);
v19 = sub_3D1F4(v32, 4LL);
v10 = sub_3D1F4(v32, 8LL);
v13 = sub_3D1F4(v32, 12LL);
v17 = sub_3D1F4(v32, 0LL);
v19 = sub_3D1F4(v32, 4LL);
v10 = sub_3D1F4(v32, 8LL);
v13 = sub_3D1F4(v32, 12LL);
public void HookByConsoleDebugger2(){
    emulator.attach().addBreakPoint(module.base + 0x3D1F4, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            emulator.traceCode(module.base,module.base+module.size);
            RegisterContext context = emulator.getContext();
            int a2 = context.getIntArg(1);
            System.out.println("===========入参=================");
            System.out.println("传入数据: " + a2);
            emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                @Override
                public boolean onHit(Emulator<?> emulator, long address) {
                    RegisterContext returnContext = emulator.getContext();
                    int Value = returnContext.getIntArg(0);
                    System.out.println("============出参================"+ Value);
                    return true;
                }
            });
            return true;
        }
    });
}
public void HookByConsoleDebugger2(){
    emulator.attach().addBreakPoint(module.base + 0x3D1F4, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            emulator.traceCode(module.base,module.base+module.size);
            RegisterContext context = emulator.getContext();
            int a2 = context.getIntArg(1);
            System.out.println("===========入参=================");
            System.out.println("传入数据: " + a2);
            emulator.attach().addBreakPoint(context.getLRPointer().peer, new BreakPointCallback() {
                @Override
                public boolean onHit(Emulator<?> emulator, long address) {
                    RegisterContext returnContext = emulator.getContext();
                    int Value = returnContext.getIntArg(0);
                    System.out.println("============出参================"+ Value);
                    return true;
                }
            });
            return true;
        }

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 5
支持
分享
最新回复 (3)
雪    币: 2
活跃值: (3843)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不错不错,给你点赞
2025-10-7 23:47
0
雪    币: 293
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
66666666666
2025-10-10 17:46
0
雪    币: 4
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
666
2025-10-12 00:13
0
游客
登录 | 注册 方可回帖
返回