动静态结合分析非标准MD5算法及还原
看雪论坛作者ID:小想法
(题外话:恭喜看雪论坛ID:飞翔的猫咪,获得看雪安卓应用安全能力认证高级安全工程师!)
第一题
Cyberchef还原屏幕上显示的字符串的生成算法,点开apk是一串hex字符串。
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");}@Overridepublic 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.Runnablepublic 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;elsev4 = -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+D6↑o.data:00081000 ; JNI_OnLoad+D8↑o ....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] BYREFstd::string v9; // [sp+3Ch] [bp-84h] BYREFMD5 v10; // [sp+48h] [bp-78h] BYREFif ( !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] BYREFthis->finished = 0;this->count[1] = 0;this->count[0] = 0;//下面是标准的MD5缓冲区初始化this->state[0] = 1732584193; //0x67452301this->state[1] = -271733879; //0xEFCDAB89this->state[2] = -1732584194; //0x98BADCFEthis->state[3] = 271733878; //0x10325476std::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); //0xD76AA478v116 = v98 + v2;v3 = __ROR4__((v82 & ~(v98 + v2) | v98 & (v98 + v2)) + v133 + v65 - 389564586, 20); //0xE8C7B756v66 = 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")。
第二题
网上找源码跑起来(任何语言均可),点开apk是一串hex字符串。
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");}@Overridepublic 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.Runnablepublic 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] BYREFstd::string v9; // [sp+3Ch] [bp-84h] BYREFMD5 v10; // [sp+48h] [bp-78h] BYREFif ( !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] BYREFthis->finished = 0;this->count[1] = 0;this->count[0] = 0;//下面初始化常量被魔改了,同时要注意state[]顺序this->state[2] = -1164378404; //0xBA98FEDCthis->state[3] = 839939668; //0x32107654this->state[0] = 1164378403; //0x45670123this->state[1] = -839939669; //0xCDEF89ABstd::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 hashuint32_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;//0x67452301h1 = 0xCDEF89AB;//0xefcdab89h2 = 0xBA98FEDC;//0x98badcfeh3 = 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 messagefor (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 ≤ 15for (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;}// cleanupfree(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 + saltsize_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;}
运行,正确。
第三题
抠F5后的算法跑起来。
点开apk是一串hex字符串。
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] BYREFstd::string v9; // [sp+3Ch] [bp-84h] BYREFMD5 v10; // [sp+48h] [bp-78h] BYREFif ( !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; // r1uint 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; // t2uint v3; // t2int v4; // t2int v5; // t2int v6; // t2int v7; // t2int v8; // t2int v9; // t2int v10; // t2int v11; // t2int v12; // t2int v13; // t2int v14; // t2int v15; // t2int v16; // t2int v17; // t2int v18; // t2int v19; // t2int v20; // t2int v21; // t2int v22; // t2int v23; // t2int v24; // t2int v25; // t2int v26; // t2int v27; // t2int v28; // t2int v29; // t2int v30; // t2int v31; // t2int v32; // t2int v33; // t2int v34; // t2int v35; // t2int v36; // t2int v37; // t2int v38; // t2int v39; // t2int v40; // t2int v41; // t2int v42; // t2int v43; // t2int v44; // t2int v45; // t2int v46; // t2int v47; // t2int v48; // t2int v49; // t2int v50; // t2int v51; // t2int v52; // t2int v53; // t2int v54; // t2int v55; // t2int v56; // t2int v57; // t2int v58; // t2int v59; // t2int v60; // t2int v61; // t2int v62; // t2int v63; // t2uint 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] BYREFuint 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] BYREFif (!(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;elsev2 = 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”:
看雪ID:小想法
https://bbs.pediy.com/user-home-919212.htm
# 往期推荐
1.进程 Dump & PE unpacking & IAT 修复 - Windows 篇
2.NtSocket的稳定实现,Client与Server的简单封装,以及SocketAsyncSelect的一种APC实现
3.如何保护自己的代码?给自己的代码添加NoChange属性
球分享
球点赞
球在看
点击“阅读原文”,了解更多!