看雪论坛作者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");
}
@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+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] 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")。
网上找源码跑起来(任何语言均可),点开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");
}
@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 amounts
const 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;
}
运行,正确。
抠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] 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”:
看雪ID:小想法
https://bbs.pediy.com/user-home-919212.htm
# 往期推荐
1.进程 Dump & PE unpacking & IAT 修复 - Windows 篇
2.NtSocket的稳定实现,Client与Server的简单封装,以及SocketAsyncSelect的一种APC实现
3.如何保护自己的代码?给自己的代码添加NoChange属性
球分享
球点赞
球在看
点击“阅读原文”,了解更多!