动静态结合分析非标准MD5算法及还原

admin 2022年10月16日18:22:08评论70 views字数 21787阅读72分37秒阅读模式

动静态结合分析非标准MD5算法及还原

看雪论坛作者ID:小想法


(题外话:恭喜看雪论坛ID:飞翔的猫咪,获得看雪安卓应用安全能力认证高级安全工程师!)



第一题


Cyberchef还原屏幕上显示的字符串的生成算法,点开apk是一串hex字符串。

动静态结合分析非标准MD5算法及还原

jadx查看主要代码,显然关键是 native方法a2w3mtestSign("roysue")。

package com.roysue.easyso1; import android.os.Bundle;import android.util.Log;import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity; /* loaded from: classes.dex */public class MainActivity extends AppCompatActivity {    public static native String Sign(String str);     public static native String a2w3mtestSign(String str);     public static native String decrypt(String str);     public static native String method01(String str);     public native String stringFromJNI();     static {        System.loadLibrary("roysue");    }      @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView tv = (TextView) findViewById(R.id.sample_text);        tv.setText(a2w3mtestSign("roysue"));        new Thread() { // from class: com.roysue.easyso1.MainActivity.1            @Override // java.lang.Thread, java.lang.Runnable            public void run() {                while (true) {                    try {                        Thread.sleep(2000L);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    Log.i("roysueeasyso1", MainActivity.method01("r0syue"));                    Log.i("roysueSIGN", MainActivity.Sign("requestUserInfo"));                }            }        }.start();    }}


ida打开libroysue.so,导出函数中找不到a2w3mtestSign()。于是查看JNI_OnLoad()。

jint JNI_OnLoad(JavaVM *vm, void *reserved){  jint v4; // [sp+Ch] [bp-14h]  void *env; // [sp+10h] [bp-10h] BYREF   //...省略部分代码  env = 0;  if ( _JavaVM::GetEnv(vm, &env, 65542) )    return -1;  if ( !env )    _assert2(      "/root/Desktop/2W3Mtest/easyso1/app/src/main/cpp/roysue.cpp",      200,      "jint JNI_OnLoad(JavaVM *, void *)",      "env != nullptr");  if ( registerMethods((JNIEnv *)env, "com/roysue/easyso1/MainActivity", method_table, 3) )    v4 = 65542;  else    v4 = -1;  return v4;}


跟进registerMethods()的method_table,发现aA2w3mtestsign()是动态注册的。

.data:00081000 ; JNINativeMethod method_table[3].data:00081000 _ZL12method_table JNINativeMethod <aDecrypt, aLjavaLangStrin_1, .data:00081000                                         ; DATA XREF: JNI_OnLoad+D6o.data:00081000                                         ; JNI_OnLoad+D8o ....data:00081000                                  _Z8method02P7_JNIEnvP7_jclassP8_jstring+1> ; fuck2(_JNIEnv *,_jclass *,_jstring *) ....data:00081000                 JNINativeMethod <aSign, aLjavaLangStrin_1, .data:00081000                                  _Z4fuckP7_JNIEnvP7_jclassP8_jstring+1>.data:00081000                 JNINativeMethod <aA2w3mtestsign, aLjavaLangStrin_1, .data:00081000                                  _Z5fuck2P7_JNIEnvP7_jclassP8_jstring+1>


查看funck2():

jstring __fastcall fuck2(JNIEnv *env, jclass jcls, jstring str_){  unsigned __int8 *bytes; // [sp+8h] [bp-B8h]  unsigned __int8 *__s; // [sp+1Ch] [bp-A4h]  jstring v7; // [sp+2Ch] [bp-94h]  std::string v8; // [sp+30h] [bp-90h] BYREF  std::string v9; // [sp+3Ch] [bp-84h] BYREF  MD5 v10; // [sp+48h] [bp-78h] BYREF   if ( !str_ )    return 0;  __s = (unsigned __int8 *)_JNIEnv::GetStringUTFChars(env, str_, 0);  std::string::basic_string<decltype(nullptr)>(&v8, __s);  MD5::MD5(&v10, &v8);  MD5::toStr(&v9, &v10);  bytes = (unsigned __int8 *)std::string::c_str(&v9);  v7 = _JNIEnv::NewStringUTF(env, bytes);  std::string::~string(&v9);  std::string::~string(&v8);  return v7;}


查看MD5::MD5():

void __fastcall MD5::MD5(MD5 *this, const std::string *message){  std::string::size_type len; // [sp+0h] [bp-38h]  byte *input; // [sp+4h] [bp-34h]  std::string v5; // [sp+20h] [bp-18h] BYREF   this->finished = 0;  this->count[1] = 0;  this->count[0] = 0;   //下面是标准的MD5缓冲区初始化  this->state[0] = 1732584193; //0x67452301  this->state[1] = -271733879; //0xEFCDAB89  this->state[2] = -1732584194; //0x98BADCFE  this->state[3] = 271733878; //0x10325476   std::operator+<char>(&v5, message, "kanxue"); //原输入的后面拼接了"kanxue"  input = std::string::c_str(&v5);  len = std::string::length(&v5);  MD5::init(this, input, len);  std::string::~string(&v5);}


把MD5::transform()出现的-680876936、-389564586等转换成hex正数之后就会发现是标准的MD5 T表。

void __fastcall MD5::transform(MD5 *this, const byte *block){  //...省略...   v115 = this->state[0];  v98 = this->state[1];  v82 = this->state[2];  v65 = this->state[3];  MD5::decode(this, block, &output, 0x40u);   v2 = __ROR4__((v65 & ~v98 | v82 & v98) + output + v115 - 680876936, 25); //0xD76AA478  v116 = v98 + v2;  v3 = __ROR4__((v82 & ~(v98 + v2) | v98 & (v98 + v2)) + v133 + v65 - 389564586, 20); //0xE8C7B756  v66 = v116 + v3;  v4 = __ROR4__((v98 & ~(v116 + v3) | v116 & (v116 + v3)) + v134 + v82 + 606105819, 15); //0x242070DB  //...省略...  this->state[0] += v131;  this->state[1] += v114;  this->state[2] += v81 + v63;  this->state[3] += v81;}


最后的MD5::toStr()中MD5::getDigest()是在做标准MD5的Encode和Update,最后再以hex输出。所以整体算法是一个MD5+Salt,即MD5("roysue" + "kanxue")。
动静态结合分析非标准MD5算法及还原



第二题


网上找源码跑起来(任何语言均可),点开apk是一串hex字符串。

动静态结合分析非标准MD5算法及还原


jadx查看主要代码,显然关键是 native方法a2w3mtestSign("roysue")。

package com.roysue.easyso1; import android.os.Bundle;import android.util.Log;import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity; /* loaded from: classes.dex */public class MainActivity extends AppCompatActivity {    public static native String Sign(String str);     public static native String a2w3mtestSign(String str);     public static native String decrypt(String str);     public static native String method01(String str);     public native String stringFromJNI();     static {        System.loadLibrary("roysue");    }      @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView tv = (TextView) findViewById(R.id.sample_text);        tv.setText(a2w3mtestSign("roysue"));        new Thread() { // from class: com.roysue.easyso1.MainActivity.1            @Override // java.lang.Thread, java.lang.Runnable            public void run() {                while (true) {                    try {                        Thread.sleep(2000L);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    Log.i("roysueeasyso1", MainActivity.method01("r0syue"));                    Log.i("roysueSIGN", MainActivity.Sign("requestUserInfo"));                }            }        }.start();    }}


ida打开libroysue.so,导出函数中找不到a2w3mtestSign()。参照题目1从JNI_OnLoad()的registerMethods()参数method_table找到其被动态注册成了fuck2()。

jstring __fastcall fuck2(JNIEnv *env, jclass jcls, jstring str_){  unsigned __int8 *bytes; // [sp+8h] [bp-B8h]  unsigned __int8 *__s; // [sp+1Ch] [bp-A4h]  jstring v7; // [sp+2Ch] [bp-94h]  std::string v8; // [sp+30h] [bp-90h] BYREF  std::string v9; // [sp+3Ch] [bp-84h] BYREF  MD5 v10; // [sp+48h] [bp-78h] BYREF   if ( !str_ )    return 0;  __s = (unsigned __int8 *)_JNIEnv::GetStringUTFChars(env, str_, 0);  std::string::basic_string<decltype(nullptr)>(&v8, __s);  MD5::MD5(&v10, &v8);  MD5::toStr(&v9, &v10);  bytes = (unsigned __int8 *)std::string::c_str(&v9);  v7 = _JNIEnv::NewStringUTF(env, bytes);  std::string::~string(&v9);  std::string::~string(&v8);  return v7;}


查看MD5(),发现被魔改过初始化的缓冲区,其余部分如题1仍是标准MD5。

void __fastcall MD5::MD5(MD5 *this, const std::string *message){  std::string::size_type len; // [sp+0h] [bp-38h]  byte *input; // [sp+4h] [bp-34h]  std::string v5; // [sp+20h] [bp-18h] BYREF   this->finished = 0;  this->count[1] = 0;  this->count[0] = 0;  //下面初始化常量被魔改了,同时要注意state[]顺序  this->state[2] = -1164378404; //0xBA98FEDC  this->state[3] = 839939668; //0x32107654  this->state[0] = 1164378403; //0x45670123  this->state[1] = -839939669; //0xCDEF89AB  std::operator+<char>(&v5, message, (const std::string::value_type *)"kanxue");  input = (byte *)std::string::c_str(&v5);  len = std::string::length(&v5);  MD5::init(this, input, len);  std::string::~string(&v5);}


根据github上面的MD5项目 https://github.com/pod32g/MD5 修改得到下面代码:

/* * Simple MD5 implementation * * Compile with: gcc -o md5 md5.c */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h> // Constants are the integer part of the sines of integers (in radians) * 2^32.const uint32_t k[64] = {    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,    0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,    0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,    0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,    0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}; // r specifies the per-round shift amountsconst uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,                      5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,                      4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,                      6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; // leftrotate function definition#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) void to_bytes(uint32_t val, uint8_t *bytes){    bytes[0] = (uint8_t)val;    bytes[1] = (uint8_t)(val >> 8);    bytes[2] = (uint8_t)(val >> 16);    bytes[3] = (uint8_t)(val >> 24);} uint32_t to_int32(const uint8_t *bytes){    return (uint32_t)bytes[0] | ((uint32_t)bytes[1] << 8) | ((uint32_t)bytes[2] << 16) | ((uint32_t)bytes[3] << 24);} void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest){     // These vars will contain the hash    uint32_t h0, h1, h2, h3;     // Message (to prepare)    uint8_t *msg = NULL;     size_t new_len, offset;    uint32_t w[16];    uint32_t a, b, c, d, i, f, g, temp;     // Initialize variables - simple count in nibbles:    // 注意这里的魔改    h0 = 0x45670123;//0x67452301    h1 = 0xCDEF89AB;//0xefcdab89    h2 = 0xBA98FEDC;//0x98badcfe    h3 = 0x32107654;//0x10325476     //Pre-processing:    //append "1" bit to message    //append "0" bits until message length in bits ≡ 448 (mod 512)    //append length mod (2^64) to message     for (new_len = initial_len + 1; new_len % (512 / 8) != 448 / 8; new_len++)        ;     msg = (uint8_t *)malloc(new_len + 8);    memcpy(msg, initial_msg, initial_len);    msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"    for (offset = initial_len + 1; offset < new_len; offset++)        msg[offset] = 0; // append "0" bits     // append the len in bits at the end of the buffer.    to_bytes(initial_len * 8, msg + new_len);    // initial_len>>29 == initial_len*8>>32, but avoids overflow.    to_bytes(initial_len >> 29, msg + new_len + 4);     // Process the message in successive 512-bit chunks:    //for each 512-bit chunk of message:    for (offset = 0; offset < new_len; offset += (512 / 8))    {         // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15        for (i = 0; i < 16; i++)            w[i] = to_int32(msg + offset + i * 4);         // Initialize hash value for this chunk:        a = h0;        b = h1;        c = h2;        d = h3;         // Main loop:        for (i = 0; i < 64; i++)        {             if (i < 16)            {                f = (b & c) | ((~b) & d);                g = i;            }            else if (i < 32)            {                f = (d & b) | ((~d) & c);                g = (5 * i + 1) % 16;            }            else if (i < 48)            {                f = b ^ c ^ d;                g = (3 * i + 5) % 16;            }            else            {                f = c ^ (b | (~d));                g = (7 * i) % 16;            }             temp = d;            d = c;            c = b;            b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);            a = temp;        }         // Add this chunk's hash to result so far:        h0 += a;        h1 += b;        h2 += c;        h3 += d;    }     // cleanup    free(msg);     //var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)    to_bytes(h0, digest);    to_bytes(h1, digest + 4);    to_bytes(h2, digest + 8);    to_bytes(h3, digest + 12);} int main(int argc, char **argv){    char *msg = "roysuekanxue"; //input + salt    size_t len;    int i;    uint8_t result[16];     len = strlen(msg);    md5((uint8_t *)msg, len, result);    for (i = 0; i < 16; i++)        printf("%2.2x", result[i]);    puts("");     return 0;}


运行,正确。
动静态结合分析非标准MD5算法及还原



第三题


抠F5后的算法跑起来。


点开apk是一串hex字符串。
动静态结合分析非标准MD5算法及还原

jadx分析Java层和ida找动态注册的函数参考题目一和题目二的解题,这里直接定位到fuck2()。

jstring __fastcall fuck2(JNIEnv *env, jclass jcls, jstring str_){  unsigned __int8 *bytes; // [sp+8h] [bp-B8h]  unsigned __int8 *__s; // [sp+1Ch] [bp-A4h]  jstring v7; // [sp+2Ch] [bp-94h]  std::string v8; // [sp+30h] [bp-90h] BYREF  std::string v9; // [sp+3Ch] [bp-84h] BYREF  MD5 v10; // [sp+48h] [bp-78h] BYREF   if ( !str_ )    return 0;  __s = (unsigned __int8 *)_JNIEnv::GetStringUTFChars(env, str_, 0);  std::string::basic_string<decltype(nullptr)>(&v8, __s);  MD5::MD5(&v10, &v8);  MD5::toStr(&v9, &v10);  bytes = (unsigned __int8 *)std::string::c_str(&v9);  v7 = _JNIEnv::NewStringUTF(env, bytes);  std::string::~string(&v9);  std::string::~string(&v8);  return v7;}


要抠算法主要就是拿出MD5的MD5::MD5()、MD5::toStr()、MD5::init()、MD5::transform()、MD5::decode()、MD5::getDigest()、MD5::encode()。


md5.h

#include "ida.h"#include <string>  class MD5 {public:    static unsigned char PADDING[64];     static unsigned char HEX_NUMBERS[16];    int finished;    uint count[2];    uint state[4];    uchar buffer[64];    uchar digest[16];     static void md5(MD5 *ctx, const std::string *message);     static void init(MD5 *ctx, _BYTE *input, size_t len);     static void transform(MD5 *ctx, const uint8 *block);     static void decode(MD5 *ctx, const uint8 *input, int *output, size_t length);     static void toStr(std::string *retstr, MD5 *ctx);     static _BYTE *getDigest(MD5 *ctx);     static void encode(MD5 *ctx, uint *input, uchar *output, size_t length);};


md5.cpp

#include "MD5.h"#include "android/log.h" unsigned char MD5::PADDING[] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char MD5::HEX_NUMBERS[] = {        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; void MD5::md5(MD5 *ctx, const std::string *message) {    size_t len; // [sp+0h] [bp-38h]     ctx->finished = 0;    ctx->count[1] = 0;    ctx->count[0] = 0;    ctx->state[2] = 0xBA98FEDC;    ctx->state[3] = 0x32107654;    ctx->state[0] = 0x45670123;    ctx->state[1] = 0xCDEF89AB;    const char *input = (*message).c_str();    len = (*message).length();    MD5::init(ctx, (uint8 *) input, len);} void MD5::init(MD5 *ctx, uint8 *input, size_t len) {    uint v3; // r1    uint v5; // [sp+14h] [bp-1Ch]    uint i; // [sp+18h] [bp-18h]     ctx->finished = 0;    v5 = (ctx->count[0] >> 3) & 0x3F;    v3 = ctx->count[0] + 8 * len;    ctx->count[0] = v3;    if (v3 < 8 * len)        ++ctx->count[1];    ctx->count[1] += len >> 29;    if (len < 64 - v5) {        i = 0;    } else {        memcpy(&ctx->buffer[v5], input, 64 - v5);        MD5::transform(ctx, ctx->buffer);        for (i = 64 - v5; i + 63 < len; i += 64)            MD5::transform(ctx, &input[i]);        v5 = 0;    }    memcpy(&ctx->buffer[v5], &input[i], len - i);} void MD5::transform(MD5 *ctx, const uint8 *block) {    uint v2; // t2    uint v3; // t2    int v4; // t2    int v5; // t2    int v6; // t2    int v7; // t2    int v8; // t2    int v9; // t2    int v10; // t2    int v11; // t2    int v12; // t2    int v13; // t2    int v14; // t2    int v15; // t2    int v16; // t2    int v17; // t2    int v18; // t2    int v19; // t2    int v20; // t2    int v21; // t2    int v22; // t2    int v23; // t2    int v24; // t2    int v25; // t2    int v26; // t2    int v27; // t2    int v28; // t2    int v29; // t2    int v30; // t2    int v31; // t2    int v32; // t2    int v33; // t2    int v34; // t2    int v35; // t2    int v36; // t2    int v37; // t2    int v38; // t2    int v39; // t2    int v40; // t2    int v41; // t2    int v42; // t2    int v43; // t2    int v44; // t2    int v45; // t2    int v46; // t2    int v47; // t2    int v48; // t2    int v49; // t2    int v50; // t2    int v51; // t2    int v52; // t2    int v53; // t2    int v54; // t2    int v55; // t2    int v56; // t2    int v57; // t2    int v58; // t2    int v59; // t2    int v60; // t2    int v61; // t2    int v62; // t2    int v63; // t2    uint v65; // [sp+14h] [bp-5Ch]    int v66; // [sp+14h] [bp-5Ch]    int v67; // [sp+14h] [bp-5Ch]    int v68; // [sp+14h] [bp-5Ch]    int v69; // [sp+14h] [bp-5Ch]    int v70; // [sp+14h] [bp-5Ch]    int v71; // [sp+14h] [bp-5Ch]    int v72; // [sp+14h] [bp-5Ch]    int v73; // [sp+14h] [bp-5Ch]    int v74; // [sp+14h] [bp-5Ch]    int v75; // [sp+14h] [bp-5Ch]    int v76; // [sp+14h] [bp-5Ch]    int v77; // [sp+14h] [bp-5Ch]    int v78; // [sp+14h] [bp-5Ch]    int v79; // [sp+14h] [bp-5Ch]    int v80; // [sp+14h] [bp-5Ch]    int v81; // [sp+14h] [bp-5Ch]    uint v82; // [sp+18h] [bp-58h]    int v83; // [sp+18h] [bp-58h]    int v84; // [sp+18h] [bp-58h]    int v85; // [sp+18h] [bp-58h]    int v86; // [sp+18h] [bp-58h]    int v87; // [sp+18h] [bp-58h]    int v88; // [sp+18h] [bp-58h]    int v89; // [sp+18h] [bp-58h]    int v90; // [sp+18h] [bp-58h]    int v91; // [sp+18h] [bp-58h]    int v92; // [sp+18h] [bp-58h]    int v93; // [sp+18h] [bp-58h]    int v94; // [sp+18h] [bp-58h]    int v95; // [sp+18h] [bp-58h]    int v96; // [sp+18h] [bp-58h]    int v97; // [sp+18h] [bp-58h]    uint v98; // [sp+1Ch] [bp-54h]    int v99; // [sp+1Ch] [bp-54h]    int v100; // [sp+1Ch] [bp-54h]    int v101; // [sp+1Ch] [bp-54h]    int v102; // [sp+1Ch] [bp-54h]    int v103; // [sp+1Ch] [bp-54h]    int v104; // [sp+1Ch] [bp-54h]    int v105; // [sp+1Ch] [bp-54h]    int v106; // [sp+1Ch] [bp-54h]    int v107; // [sp+1Ch] [bp-54h]    int v108; // [sp+1Ch] [bp-54h]    int v109; // [sp+1Ch] [bp-54h]    int v110; // [sp+1Ch] [bp-54h]    int v111; // [sp+1Ch] [bp-54h]    int v112; // [sp+1Ch] [bp-54h]    int v113; // [sp+1Ch] [bp-54h]    uint v114; // [sp+20h] [bp-50h]    int v115; // [sp+20h] [bp-50h]    int v116; // [sp+20h] [bp-50h]    int v117; // [sp+20h] [bp-50h]    int v118; // [sp+20h] [bp-50h]    int v119; // [sp+20h] [bp-50h]    int v120; // [sp+20h] [bp-50h]    int v121; // [sp+20h] [bp-50h]    int v122; // [sp+20h] [bp-50h]    int v123; // [sp+20h] [bp-50h]    int v124; // [sp+20h] [bp-50h]    int v125; // [sp+20h] [bp-50h]    int v126; // [sp+20h] [bp-50h]    int v127; // [sp+20h] [bp-50h]    int v128; // [sp+20h] [bp-50h]    int v129; // [sp+20h] [bp-50h]    int v130; // [sp+20h] [bp-50h]    int output; // [sp+24h] [bp-4Ch] BYREF    uint v132; // [sp+28h] [bp-48h]    int v133; // [sp+2Ch] [bp-44h]    int v134; // [sp+30h] [bp-40h]    int v135; // [sp+34h] [bp-3Ch]    int v136; // [sp+38h] [bp-38h]    int v137; // [sp+3Ch] [bp-34h]    int v138; // [sp+40h] [bp-30h]    int v139; // [sp+44h] [bp-2Ch]    int v140; // [sp+48h] [bp-28h]    int v141; // [sp+4Ch] [bp-24h]    int v142; // [sp+50h] [bp-20h]    int v143; // [sp+54h] [bp-1Ch]    int v144; // [sp+58h] [bp-18h]    int v145; // [sp+5Ch] [bp-14h]    int v146; // [sp+60h] [bp-10h]     v114 = ctx->state[0];    v98 = ctx->state[1];    v82 = ctx->state[2];    v65 = ctx->state[3];    MD5::decode(ctx, block, &output, 0x40u);    v2 = __ROR__((v65 & ~v98 | v82 & v98) + output + v114 - 680876936, 25);    v115 = v98 + v2;    v3 = __ROR__((v82 & ~(v98 + v2) | v98 & (v98 + v2)) + v132 + v65 - 389564586, 20);    v66 = v115 + v3;    v4 = __ROR__((v98 & ~(v115 + v3) | v115 & (v115 + v3)) + v133 + v82 + 606105819, 15);    v83 = v66 + v4;    v5 = __ROR__((v115 & ~(v66 + v4) | v66 & (v66 + v4)) + v134 + v98 - 1044525330, 10);    v99 = v83 + v5;    v6 = __ROR__((v66 & ~(v83 + v5) | v83 & (v83 + v5)) + v135 + v115 - 176418897, 25);    v116 = v99 + v6;    v7 = __ROR__((v83 & ~(v99 + v6) | v99 & (v99 + v6)) + v136 + v66 + 1200080426, 20);    v67 = v116 + v7;    v8 = __ROR__((v99 & ~(v116 + v7) | v116 & (v116 + v7)) + v137 + v83 - 1473231341, 15);    v84 = v67 + v8;    v9 = __ROR__((v116 & ~(v67 + v8) | v67 & (v67 + v8)) + v138 + v99 - 45705983, 10);    v100 = v84 + v9;    v10 = __ROR__((v67 & ~(v84 + v9) | v84 & (v84 + v9)) + v139 + v116 + 1770035416, 25);    v117 = v100 + v10;    v11 = __ROR__((v84 & ~(v100 + v10) | v100 & (v100 + v10)) + v140 + v67 - 1958414417, 20);    v68 = v117 + v11;    v12 = __ROR__((v100 & ~(v117 + v11) | v117 & (v117 + v11)) + v141 + v84 - 42063, 15);    v85 = v68 + v12;    v13 = __ROR__((v117 & ~(v68 + v12) | v68 & (v68 + v12)) + v142 + v100 - 1990404162, 10);    v101 = v85 + v13;    v14 = __ROR__((v68 & ~(v85 + v13) | v85 & (v85 + v13)) + v143 + v117 + 1804603682, 25);    v118 = v101 + v14;    v15 = __ROR__((v85 & ~(v101 + v14) | v101 & (v101 + v14)) + v144 + v68 - 40341101, 20);    v69 = v118 + v15;    v16 = __ROR__((v101 & ~(v118 + v15) | v118 & (v118 + v15)) + v145 + v85 - 1502002290, 15);    v86 = v69 + v16;    v17 = __ROR__((v118 & ~(v69 + v16) | v69 & (v69 + v16)) + v146 + v101 + 1236535329, 10);    v102 = v86 + v17;    v18 = __ROR__(((v86 + v17) & v69 | v86 & ~v69) + v132 + v118 - 165796510, 27);    v119 = v102 + v18;    v19 = __ROR__(((v102 + v18) & v86 | v102 & ~v86) + v137 + v69 - 1069501632, 23);    v70 = v119 + v19;    v87 = v119 + v19 + __ROR__(((v119 + v19) & v102 | v119 & ~v102) + v142 + v86 + 643717713, 18);    v20 = __ROR__((v87 & v119 | (v119 + v19) & ~v119) + output + v102 - 373897302, 12);    v103 = v87 + v20;    v21 = __ROR__(((v87 + v20) & v70 | v87 & ~v70) + v136 + v119 - 701558691, 27);    v120 = v103 + v21;    v22 = __ROR__(((v103 + v21) & v87 | v103 & ~v87) + v141 + v70 + 38016083, 23);    v71 = v120 + v22;    v23 = __ROR__(((v120 + v22) & v103 | v120 & ~v103) + v146 + v87 - 660478335, 18);    v88 = v71 + v23;    v24 = __ROR__(((v71 + v23) & v120 | v71 & ~v120) + v135 + v103 - 405537848, 12);    v104 = v88 + v24;    v25 = __ROR__(((v88 + v24) & v71 | v88 & ~v71) + v140 + v120 + 568446438, 27);    v121 = v104 + v25;    v26 = __ROR__(((v104 + v25) & v88 | v104 & ~v88) + v145 + v71 - 1019803690, 23);    v72 = v121 + v26;    v27 = __ROR__(((v121 + v26) & v104 | v121 & ~v104) + v134 + v88 - 187363961, 18);    v89 = v72 + v27;    v28 = __ROR__(((v72 + v27) & v121 | v72 & ~v121) + v139 + v104 + 1163531501, 12);    v105 = v89 + v28;    v29 = __ROR__(((v89 + v28) & v72 | v89 & ~v72) + v144 + v121 - 1444681467, 27);    v122 = v105 + v29;    v30 = __ROR__(((v105 + v29) & v89 | v105 & ~v89) + v133 + v72 - 51403784, 23);    v73 = v122 + v30;    v31 = __ROR__(((v122 + v30) & v105 | v122 & ~v105) + v138 + v89 + 1735328473, 18);    v90 = v73 + v31;    v32 = __ROR__(((v73 + v31) & v122 | v73 & ~v122) + v143 + v105 - 1926607734, 12);    v106 = v90 + v32;    v33 = __ROR__(((v90 + v32) ^ v90 ^ v73) + v136 + v122 - 378558, 28);    v123 = v106 + v33;    v34 = __ROR__(((v106 + v33) ^ v106 ^ v90) + v139 + v73 - 2022574463, 21);    v74 = v123 + v34;    v35 = __ROR__(((v123 + v34) ^ v123 ^ v106) + v142 + v90 + 1839030562, 16);    v91 = v74 + v35;    v36 = __ROR__(((v74 + v35) ^ v74 ^ v123) + v145 + v106 - 35309556, 9);    v107 = v91 + v36;    v37 = __ROR__(((v91 + v36) ^ v91 ^ v74) + v132 + v123 - 1530992060, 28);    v124 = v107 + v37;    v38 = __ROR__(((v107 + v37) ^ v107 ^ v91) + v135 + v74 + 1272893353, 21);    v75 = v124 + v38;    v39 = __ROR__(((v124 + v38) ^ v124 ^ v107) + v138 + v91 - 155497632, 16);    v92 = v75 + v39;    v40 = __ROR__(((v75 + v39) ^ v75 ^ v124) + v141 + v107 - 1094730640, 9);    v108 = v92 + v40;    v41 = __ROR__(((v92 + v40) ^ v92 ^ v75) + v144 + v124 + 681279174, 28);    v125 = v108 + v41;    v42 = __ROR__(((v108 + v41) ^ v108 ^ v92) + output + v75 - 358537222, 21);    v76 = v125 + v42;    v43 = __ROR__(((v125 + v42) ^ v125 ^ v108) + v134 + v92 - 722521979, 16);    v93 = v76 + v43;    v44 = __ROR__(((v76 + v43) ^ v76 ^ v125) + v137 + v108 + 76029189, 9);    v109 = v93 + v44;    v45 = __ROR__(((v93 + v44) ^ v93 ^ v76) + v140 + v125 - 640364487, 28);    v126 = v109 + v45;    v46 = __ROR__(((v109 + v45) ^ v109 ^ v93) + v143 + v76 - 421815835, 21);    v77 = v126 + v46;    v47 = __ROR__(((v126 + v46) ^ v126 ^ v109) + v146 + v93 + 530742520, 16);    v94 = v77 + v47;    v48 = __ROR__(((v77 + v47) ^ v77 ^ v126) + v133 + v109 - 995338651, 9);    v110 = v94 + v48;    v49 = __ROR__((v94 ^ ((v94 + v48) | ~v77)) + output + v126 - 198630844, 26);    v127 = v110 + v49;    v50 = __ROR__((v110 ^ ((v110 + v49) | ~v94)) + v138 + v77 + 1126891415, 22);    v78 = v127 + v50;    v51 = __ROR__((v127 ^ ((v127 + v50) | ~v110)) + v145 + v94 - 1416354905, 17);    v95 = v78 + v51;    v52 = __ROR__((v78 ^ ((v78 + v51) | ~v127)) + v136 + v110 - 57434055, 11);    v111 = v95 + v52;    v53 = __ROR__((v95 ^ ((v95 + v52) | ~v78)) + v143 + v127 + 1700485571, 26);    v128 = v111 + v53;    v54 = __ROR__((v111 ^ ((v111 + v53) | ~v95)) + v134 + v78 - 1894986606, 22);    v79 = v128 + v54;    v55 = __ROR__((v128 ^ ((v128 + v54) | ~v111)) + v141 + v95 - 1051523, 17);    v96 = v79 + v55;    v56 = __ROR__((v79 ^ ((v79 + v55) | ~v128)) + v132 + v111 - 2054922799, 11);    v112 = v96 + v56;    v57 = __ROR__((v96 ^ ((v96 + v56) | ~v79)) + v139 + v128 + 1873313359, 26);    v129 = v112 + v57;    v58 = __ROR__((v112 ^ ((v112 + v57) | ~v96)) + v146 + v79 - 30611744, 22);    v80 = v129 + v58;    v59 = __ROR__((v129 ^ ((v129 + v58) | ~v112)) + v137 + v96 - 1560198380, 17);    v97 = v80 + v59;    v60 = __ROR__((v80 ^ ((v80 + v59) | ~v129)) + v144 + v112 + 1309151649, 11);    v113 = v97 + v60;    v61 = __ROR__((v97 ^ ((v97 + v60) | ~v80)) + v135 + v129 - 145523070, 26);    v130 = v113 + v61;    v62 = __ROR__((v113 ^ ((v113 + v61) | ~v97)) + v142 + v80 - 1120210379, 22);    v81 = v130 + v62;    v63 = __ROR__((v130 ^ ((v130 + v62) | ~v113)) + v133 + v97 + 718787259, 17);    ctx->state[0] += v81 + v63 + __ROR__((v81 ^ ((v81 + v63) | ~v130)) + v140 + v113 - 343485551, 11);    ctx->state[1] += v130;    ctx->state[2] += v81 + v63;    ctx->state[3] += v81;} void MD5::decode(MD5 *ctx, const uint8 *input, int *output, size_t length) {    size_t i; // [sp+0h] [bp-18h]    int v5; // [sp+4h] [bp-14h]     v5 = 0;    for (i = 0; i < length; i += 4)        output[v5++] = *(_DWORD *) &input[i];} void MD5::toStr(std::string *retstr, MD5 *ctx) {    int v4; // [sp+10h] [bp-28h]    unsigned int i; // [sp+14h] [bp-24h]    const _BYTE *v6; // [sp+24h] [bp-14h]     v6 = MD5::getDigest(ctx);    (*retstr).reserve(0x20u);    for (i = 0; i <= 0xF; ++i) {        v4 = v6[i];        retstr->append(reinterpret_cast<const char *>(MD5::HEX_NUMBERS[v4 >> 4]));        retstr->append(reinterpret_cast<const char *>(MD5::HEX_NUMBERS[v4 - (v4 & 0xFFFFFFF0)]));    }} _BYTE *MD5::getDigest(MD5 *ctx) {    size_t v2; // [sp+8h] [bp-48h]    int v4; // [sp+18h] [bp-38h]    __int64 v5; // [sp+20h] [bp-30h]    __int64 v6; // [sp+28h] [bp-28h]    __int64 v7; // [sp+30h] [bp-20h]    _BYTE output[8]; // [sp+3Ch] [bp-14h] BYREF     if (!(ctx->finished << 31)) {        ctx->finished = 1;        v6 = *(_QWORD *) ctx->state;        v7 = *(_QWORD *) &ctx->state[2];        v5 = *(_QWORD *) ctx->count;        MD5::encode(ctx, ctx->count, output, 8u);        v4 = (ctx->count[0] >> 3) & 0x3F;        if (v4 > 0x37)            v2 = 120 - v4;        else            v2 = 56 - v4;        MD5::init(ctx, MD5::PADDING, v2);        MD5::init(ctx, output, 8u);        MD5::encode(ctx, ctx->state, ctx->digest, 0x10u);        *(_QWORD *) ctx->state = v6;        *(_QWORD *) &ctx->state[2] = v7;        *(_QWORD *) ctx->count = v5;    }    return ctx->digest;} void MD5::encode(MD5 *ctx, uint *input, _BYTE *output, size_t length) {    size_t i; // [sp+0h] [bp-18h]    int v5; // [sp+4h] [bp-14h]     v5 = 0;    for (i = 0; i < length; i += 4) {        *(_WORD *) &output[i] = input[v5];        output[i + 2] = HIWORD(input[v5]);        output[i + 3] = HIBYTE(input[v5++]);    }}


运行传入“roysuekanxue”:
动静态结合分析非标准MD5算法及还原




动静态结合分析非标准MD5算法及还原


看雪ID:小想法

https://bbs.pediy.com/user-home-919212.htm

*本文由看雪论坛 小想法 原创,转载请注明来自看雪社区

动静态结合分析非标准MD5算法及还原秋季班火热招生中动静态结合分析非标准MD5算法及还原


# 往期推荐

1.进程 Dump & PE unpacking & IAT 修复 - Windows 篇

2.NtSocket的稳定实现,Client与Server的简单封装,以及SocketAsyncSelect的一种APC实现

3.如何保护自己的代码?给自己的代码添加NoChange属性

4.针对某会议软件,简单研究其CEF框架

5.PE加载过程 FileBuffer-ImageBuffer

6.APT 双尾蝎样本分析



动静态结合分析非标准MD5算法及还原



动静态结合分析非标准MD5算法及还原

球分享

动静态结合分析非标准MD5算法及还原

球点赞

动静态结合分析非标准MD5算法及还原

球在看



动静态结合分析非标准MD5算法及还原

点击“阅读原文”,了解更多!

原文始发于微信公众号(看雪学苑):动静态结合分析非标准MD5算法及还原

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月16日18:22:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   动静态结合分析非标准MD5算法及还原http://cn-sec.com/archives/1352853.html

发表评论

匿名网友 填写信息