国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【reverse】手把手帶你基于dll實(shí)現(xiàn)多次SMC

這篇具有很好參考價(jià)值的文章主要介紹了【reverse】手把手帶你基于dll實(shí)現(xiàn)多次SMC。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

引言

SMC,即self modifying code,自修改代碼,逆向入門SMC可以看一下我的題解。我打算實(shí)現(xiàn)一個(gè)類似于【網(wǎng)鼎杯2020青龍組】jocker的SMC方案。這個(gè)方案不需要用到匯編,因此門檻極低(連小小前端都能學(xué)會(huì))。為什么要基于dll呢?因?yàn)榇a段加密功能是通過(guò)外部python腳本完成的,將自修改代碼拆分為獨(dú)立dll實(shí)現(xiàn)上更方便。

倉(cāng)庫(kù):https://github.com/Hans774882968/self-modify-code-hello

編譯器:g++8.1.0。

本文juejin:https://juejin.cn/post/7228629361652727845/

本文CSDN:https://blog.csdn.net/hans774882968/article/details/130469189

本文52pojie:https://www.52pojie.cn/thread-1780843-1-1.html

作者:hans774882968以及hans774882968以及hans774882968

實(shí)現(xiàn)普通的dll調(diào)用

先編譯一個(gè)dll。

enc.h

#pragma once

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)

enc.cpp

#include "enc.h"

int enc_arr[14] = {67, 91, 48, 88, 80, 75, 41, 93, 116, 92, 33, 83, 68, 69};
int private_key[4] = {43, 56, 68, 62};

extern "C" __declspec (dllexport) bool can_get_flag (string s);
void internal_func();

bool can_get_flag (string s) {
    internal_func();
    int n = s.size();
    if (n != 14) return false;
    re_ (i, 0, n) {
        if ( (s[i] ^ private_key[i % 4]) != enc_arr[i]) return false;
    }
    return true;
}

void internal_func () {
    puts ("internal_func");
}

命令:

g++ enc.cpp -g -shared -o enc.dll

接下來(lái)寫一個(gè)普通的控制臺(tái)應(yīng)用來(lái)調(diào)用dll,main.cpp

#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
typedef bool (*flag_func) (string);
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)

int main() {
    HMODULE h = LoadLibrary ("enc.dll");
    // 不知道為什么,必須強(qiáng)轉(zhuǎn)才能過(guò)編譯
    flag_func can_get_flag = (flag_func) GetProcAddress (h, "can_get_flag");
    puts ("Input flag:");
    string inp;
    cin >> inp;
    if (can_get_flag (inp) ) {
        cout << "Congratulations! Your flag: " << inp << endl;
    } else {
        puts ("Incorrect flag");
    }
    return 0;
}

main.cpp不需要任何配置,直接編譯即可。

實(shí)現(xiàn)基于dll的SMC

接下來(lái)在以上代碼的基礎(chǔ)上實(shí)現(xiàn)SMC。

思路很簡(jiǎn)單:先編譯出enc.dll,接著寫一個(gè)腳本修改enc.dll,最后寫C++代碼main.cpp調(diào)用enc.dll和解密enc.dll中的加密函數(shù)。main.cpp至少需要編譯2次。

首先打開IDA,查看enc.dll待加密函數(shù)can_get_flag的文件偏移(IDA下方狀態(tài)欄會(huì)顯示光標(biāo)位置對(duì)應(yīng)的文件偏移和Virtual Address):[0x9b0, 0xa66]。然后寫一個(gè)小腳本來(lái)實(shí)現(xiàn)enc.dll的修改(TODO:有佬教教我更優(yōu)雅的做法嘛QAQ)。

enc_dll.py

enc_key = [67, 91, 48, 88, 80, 75, 41, 93, 116, 92, 33, 83, 68, 69]


def enc(content, st, ed):
    res = []
    for i in range(st, ed + 1):
        res.append(content[i] ^ enc_key[(i - st) % len(enc_key)])
    return bytes(res)


st = 0x9b0
ed = 0xa66
with open('enc.dll', 'rb') as f1:
    content = f1.read()
    res = [content[:st]]
    enc_res = enc(content, st, ed)
    res.append(enc_res)
    res.append(content[ed + 1:])
    with open('enc_e.dll', 'wb') as f2:
        for r in res:
            f2.write(r)

最后修改一下main.cpp,加上:

  1. 修改內(nèi)存頁(yè)為可寫的代碼,change_page函數(shù)。主要是用了Windows APIVirtualProtect函數(shù)。
  2. 運(yùn)行時(shí)解密的代碼。
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
typedef bool (*flag_func) (string);
typedef unsigned char uint8;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)

const int enc_key[14] = {67, 91, 48, 88, 80, 75, 41, 93, 116, 92, 33, 83, 68, 69};

void change_page (void *addr) {
    DWORD old;
    SYSTEM_INFO si;
    UINT64 _addr = (UINT64) addr;
    GetSystemInfo (&si);
    int page_size = si.dwPageSize;
    _addr -= (UINT64) addr % page_size;

    if (!VirtualProtect ( (PVOID) _addr, page_size, PAGE_EXECUTE_READWRITE, &old) )
        printf ("Error: %x\n", GetLastError() );

    return;
}

int main() {
    HMODULE h = LoadLibrary ("enc_e.dll");
    // 不知道為什么,必須強(qiáng)轉(zhuǎn)才能過(guò)編譯
    flag_func can_get_flag = (flag_func) GetProcAddress (h, "can_get_flag");
    change_page ( (void *) can_get_flag);
    // 故意沒(méi)有把 SMC 解密的代碼封裝為獨(dú)立函數(shù)
    int sz = 0xa66 - 0x9b0;
    uint8 *st = (uint8 *) can_get_flag, *ed = (uint8 *) (can_get_flag) + sz;
    for (uint8 *i = st; i <= ed; ++i) *i ^= enc_key[ (i - st) % 14];

    puts ("Input flag:");
    string inp;
    cin >> inp;
    if (can_get_flag (inp) ) {
        cout << "Congratulations! Your flag: " << inp << endl;
    } else {
        puts ("Incorrect flag");
    }
    return 0;
}

值得注意的是,GetProcAddress是根據(jù)dll的導(dǎo)出表來(lái)找到函數(shù)地址的,因此我們修改了can_get_flag的數(shù)據(jù)后,依舊能夠找到其地址。

用x64dbg動(dòng)態(tài)調(diào)試,進(jìn)入enc_e.dll的內(nèi)存空間,就能看到自修改代碼的效果。

基于dll實(shí)現(xiàn)多次SMC

在這里看到了一道看上去很難的題,它的第一步就是要解密多次SMC。即:解密一段代碼后,發(fā)現(xiàn)這段代碼也是SMC,于是需要繼續(xù)解密。這就導(dǎo)致你的IDApython腳本需要寫遞歸,更為復(fù)雜。我在這里打算實(shí)現(xiàn)一個(gè)多次SMC,同樣不需要直接操作匯編,門檻極低。因?yàn)槲冶容^菜,所以把這件事分為兩步:前期準(zhǔn)備、正式實(shí)現(xiàn)。前期準(zhǔn)備把多次SMC的demo代碼寫好;正式實(shí)現(xiàn)則是參考上述demo代碼,使用模板引擎來(lái)生成所需代碼,期望的效果是:在第一次編譯enc.dll后只需要進(jìn)行少量人工操作就能進(jìn)行第二次編譯。

前期準(zhǔn)備

為了實(shí)現(xiàn)多次SMC,我們需要考慮更多的問(wèn)題:

  1. 每個(gè)SMC函數(shù)的起點(diǎn)、終點(diǎn)如何確定。
  2. 有許多函數(shù)需要導(dǎo)出,許多函數(shù)所在的內(nèi)存空間要修改為可寫……

問(wèn)題2可以用代碼生成技術(shù)解決,這就是為什么我選用了模板引擎。問(wèn)題1比較棘手,我采用的可行但粗糙的做法是:讓每個(gè)SMC函數(shù)結(jié)構(gòu)相同,于是它們的大小也都相同。再通過(guò)讀dll的導(dǎo)出表,來(lái)確定每個(gè)SMC函數(shù)的起點(diǎn)。這樣每個(gè)SMC函數(shù)的起點(diǎn)和終點(diǎn)都可以確定。

操作過(guò)程:

  1. 編寫enc.h, enc.cpp,第一次編譯enc.dll(編譯命令同上)。
  2. 查看函數(shù)大小,修改enc.cpp,第二次編譯enc.dll
  3. 編寫enc_dll.py,生成enc_e.dll。
  4. 編寫、編譯main.cpp。

enc.h

#pragma once

#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
typedef unsigned char uint8;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)

enc.cpp

#include "enc.h"

extern "C" __declspec (dllexport) void change_page (void *addr);
extern "C" __declspec (dllexport) bool can_get_flag (string s);
extern "C" __declspec (dllexport) void smc1 (void);
extern "C" __declspec (dllexport) void smc2 (void);
extern "C" __declspec (dllexport) void smc3 (void);
void internal_func();

void change_page (void *addr) {
    DWORD old;
    SYSTEM_INFO si;
    UINT64 _addr = (UINT64) addr;
    GetSystemInfo (&si);
    int page_size = si.dwPageSize;
    _addr -= (UINT64) addr % page_size;

    if (!VirtualProtect ( (PVOID) _addr, page_size, PAGE_EXECUTE_READWRITE, &old) )
        printf ("Error: %x\n", GetLastError() );

    return;
}

bool can_get_flag (string s) {
    internal_func();
    const int enc_arr[14] = {67, 91, 48, 88, 80, 75, 41, 93, 116, 92, 33, 83, 68, 69};
    const int private_key[4] = {43, 56, 68, 62};
    int n = s.size();
    if (n < 14) return false;
    re_ (i, 0, 14) {
        if ( (s[i] ^ private_key[i % 4]) != enc_arr[i]) return false;
    }
    return true;
}

void internal_func () {
    puts ("internal_func");
}

const int sz1 = 0xB50 - 0xA3D;
const int sz2 = 0xC5F - 0xB6C;

void smc1() {
    const int enc_key1[14] = {55, 7, 39, 227, 9, 26, 205, 157, 109, 61, 254, 56, 207, 69};
    uint8 *st = (uint8 *) can_get_flag, *ed = (uint8 *) (can_get_flag) + sz1;
    for (uint8 *i = st; i <= ed; ++i) *i ^= enc_key1[ (i - st) % 14];
    internal_func();
}

void smc2() {
    const int enc_key2[14] = {155, 254, 177, 21, 171, 126, 74, 154, 136, 15, 99, 93, 175, 252};
    uint8 *st = (uint8 *) smc1, *ed = (uint8 *) (smc1) + sz2;
    for (uint8 *i = st; i <= ed; ++i) *i ^= enc_key2[ (i - st) % 14];
    smc1();
}

void smc3() {
    const int enc_key3[14] = {40, 124, 172, 226, 104, 12, 179, 114, 101, 183, 45, 169, 121, 164};
    uint8 *st = (uint8 *) smc2, *ed = (uint8 *) (smc2) + sz2;
    for (uint8 *i = st; i <= ed; ++i) *i ^= enc_key3[ (i - st) % 14];
    smc2();
}

注意點(diǎn):

  1. 這里的smc1~3需要盡量寫成模板引擎容易實(shí)現(xiàn)的形式,即需要高度相似。
  2. enc_arr, enc_key1等數(shù)組都應(yīng)該放到棧里,從而能被加密,否則逆向難度極低。
  3. sz1, sz2分別是can_get_flagsmc1~3的函數(shù)大小,需要先編譯一次dll,看到大小以后再進(jìn)行修改。這也是上面說(shuō)enc.dll需要編譯至少2次的原因。
  4. main.cpp負(fù)責(zé)解密smc3,隨后調(diào)用smc3實(shí)現(xiàn)所有函數(shù)的運(yùn)行時(shí)解密。

main.cpp

#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
typedef bool (*flag_func) (string);
typedef void (*cp_func) (void *);
typedef void (*smc_func) (void);
typedef unsigned char uint8;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)

const int enc_key4[14] = {16, 113, 174, 24, 78, 9, 90, 95, 207, 146, 136, 125, 69, 203};

int main() {
    HMODULE h = LoadLibrary ("enc_e.dll");
    // 不知道為什么,必須強(qiáng)轉(zhuǎn)才能過(guò)編譯
    flag_func can_get_flag = (flag_func) GetProcAddress (h, "can_get_flag");
    cp_func change_page = (cp_func) GetProcAddress (h, "change_page");
    smc_func smc1 = (smc_func) GetProcAddress (h, "smc1");
    smc_func smc2 = (smc_func) GetProcAddress (h, "smc2");
    smc_func smc3 = (smc_func) GetProcAddress (h, "smc3");
    vector<void *> funcs = { (void *) can_get_flag, (void *) smc1, (void *) smc2, (void *) smc3};
    for (auto func : funcs) {
        change_page (func);
    }
    // 故意沒(méi)有把 SMC 解密的代碼封裝為獨(dú)立函數(shù)
    const int sz2 = 0xC5F - 0xB6C;
    uint8 *st = (uint8 *) smc3, *ed = (uint8 *) (smc3) + sz2;
    for (uint8 *i = st; i <= ed; ++i) *i ^= enc_key4[ (i - st) % 14];
    smc3();

    puts ("Input flag:");
    string inp;
    cin >> inp;
    if (can_get_flag (inp) ) {
        cout << "Congratulations! Your flag: " << inp << endl;
    } else {
        puts ("Incorrect flag");
    }
    return 0;
}

注意點(diǎn):

  1. 需要修改內(nèi)存頁(yè)為可寫。
  2. 需要運(yùn)行時(shí)解密smc3,隨后調(diào)用。

enc_dll.py

import pefile

peobj = pefile.PE('enc.dll')


def get_smc_funcs():
    candidate_funcs = [[symb.name.decode('utf-8'), symb.address] for symb in peobj.DIRECTORY_ENTRY_EXPORT.symbols]
    smc_funcs = list(filter(lambda x: 'can_get_flag' in x[0] or 'smc' in x[0], candidate_funcs))
    return smc_funcs


enc_keys = {
    "can_get_flag": [55, 7, 39, 227, 9, 26, 205, 157, 109, 61, 254, 56, 207, 69],
    "smc1": [155, 254, 177, 21, 171, 126, 74, 154, 136, 15, 99, 93, 175, 252],
    "smc2": [40, 124, 172, 226, 104, 12, 179, 114, 101, 183, 45, 169, 121, 164],
    "smc3": [16, 113, 174, 24, 78, 9, 90, 95, 207, 146, 136, 125, 69, 203]
}


def enc(st, ed, enc_key):
    dat = peobj.get_data(st, ed - st + 1)
    res = bytes([v ^ enc_key[i % len(enc_key)] for i, v in enumerate(dat)])
    peobj.set_bytes_at_rva(st, res)


def main():
    smc_funcs = get_smc_funcs()
    print([[f[0], hex(f[1])] for f in smc_funcs])  # dbg
    sz1 = 0xB50 - 0xA3D
    sz2 = 0xC5F - 0xB6C
    for i, (func_name, st) in enumerate(smc_funcs):
        ed = st + (sz1 if func_name == 'can_get_flag' else sz2)
        enc_key = enc_keys[func_name]
        enc(st, ed, enc_key)
    res = peobj.write()
    with open('enc_e.dll', 'wb') as res_f:
        res_f.write(res)


if __name__ == '__main__':
    main()

和上一節(jié)《實(shí)現(xiàn)基于dll的SMC》不同,我改成了使用pefile包來(lái)進(jìn)行dll的讀寫,這樣代碼會(huì)優(yōu)雅得多。注意點(diǎn):

  1. pefile官方文檔語(yǔ)焉不詳,建議直接看源碼,<py安裝路徑>\Lib\site-packages\pefile.py。
  2. 我們需要從導(dǎo)出表讀取函數(shù)起始地址,這也是為什么需要使用pefile包。從源碼中看到,peobj.DIRECTORY_ENTRY_EXPORT.symbolsExportData[]類型,ExportDataaddress就是我們需要的函數(shù)起始地址,它是rva。所以在實(shí)現(xiàn)代碼的過(guò)程中,選用讀寫API時(shí),挑選入?yún)⒁鬄?code>rva的API即可。
  3. enc_keys是為每個(gè)SMC函數(shù)隨機(jī)生成的密鑰數(shù)組,在后文《正式實(shí)現(xiàn)》中需要做到自動(dòng)生成。

正式實(shí)現(xiàn)

有了前期準(zhǔn)備,這一步就是純體力活了。具體操作:

  1. 我們需要使用模板引擎,來(lái)生成enc.cpp, enc_dll.py, main.cpp。這里選擇了jinja2。記生成代碼的文件名為generate_files.py,寫好代碼后運(yùn)行一下,生成代碼。
  2. 編譯enc.h, enc.cpp,獲取enc.dll,查看can_get_flagsmc1的大小,修改generate_files.py,再次運(yùn)行生成代碼。接下來(lái)再次編譯enc.h, enc.cpp生成enc.dll,然后運(yùn)行enc_dll.py生成enc_e.dll。
  3. 最后編譯main.cpp即可。

相關(guān)代碼都可以在這里查看。generate_files.py

import jinja2
import random

SMC_NUM = 100
sz1 = 0xC9B - 0xA3D
sz2 = 0xDAA - 0xCB7
enc_key_obj_list = []
smc_func_names = []
smc_func_body_obj_list = []


def prepare_data():
    global smc_func_names
    for i in range(SMC_NUM + 1):
        random_enc_key = [random.randint(0, 255) for _ in range(14)]
        enc_key_obj_list.append({
            'name': ('smc%s' % i) if i else 'can_get_flag',
            'enc_key': random_enc_key,
            'enc_key_str': ', '.join([str(v) for v in random_enc_key])
        })
    smc_func_names = ['smc%s' % (i + 1) for i in range(SMC_NUM)]
    for i in range(SMC_NUM):
        # gen_main_cpp 用了 enc_key_obj_list[-1]['enc_key_str'],因此不需要再用
        smc_func_body_obj_list.append({
            'name': smc_func_names[i],
            'enc_key_str': enc_key_obj_list[i]['enc_key_str'],
            'to_decrypt': smc_func_names[i - 1] if i else 'can_get_flag',
            'to_call': smc_func_names[i - 1] if i else 'internal_func',
        })


def gen_enc_dll_py():
    fname = 'enc_dll.py.jinja'
    with open(fname, 'r', encoding='utf-8') as f:
        template = f.read()
        t = jinja2.Template(template)
        code = t.render(
            sz1=hex(sz1),
            sz2=hex(sz2),
            enc_key_obj_list=enc_key_obj_list
        )
        with open(fname[:-6], 'w', encoding='utf-8') as res_f:
            res_f.write(code)


def gen_main_cpp():
    fname = 'main.cpp.jinja'
    with open(fname, 'r', encoding='utf-8') as f:
        template = f.read()
        t = jinja2.Template(template)
        code = t.render(
            enc_key_last_str=enc_key_obj_list[-1]['enc_key_str'],
            smc_func_names=smc_func_names,
            sz2=hex(sz2)
        )
        with open(fname[:-6], 'w', encoding='utf-8') as res_f:
            res_f.write(code)


def gen_enc_cpp():
    fname = 'enc.cpp.jinja'
    with open(fname, 'r', encoding='utf-8') as f:
        template = f.read()
        t = jinja2.Template(template)
        code = t.render(
            smc_func_names=smc_func_names,
            sz1=hex(sz1),
            sz2=hex(sz2),
            smc_func_body_obj_list=smc_func_body_obj_list
        )
        with open(fname[:-6], 'w', encoding='utf-8') as res_f:
            res_f.write(code)


def main():
    prepare_data()
    gen_enc_dll_py()
    gen_main_cpp()
    gen_enc_cpp()


if __name__ == '__main__':
    main()

賞析:更簡(jiǎn)潔的SMC方案

在GitHub看到的一種很簡(jiǎn)潔的SMC方案。原理很簡(jiǎn)單:在運(yùn)行時(shí)修改一個(gè)函數(shù)(在這個(gè)例子中是malicious)的函數(shù)體,使得一個(gè)變量的初值改變,從而隨心所欲地控制函數(shù)走向的分支??梢酝咸砑臃凑{(diào)試邏輯,就體現(xiàn)了這種隨心所欲。具體實(shí)現(xiàn)如下:

  1. 首先寫一段代碼,在這個(gè)例子中是change_page函數(shù),將SMC函數(shù)malicious所在的內(nèi)存頁(yè)修改為可寫。
  2. 然后編譯一次,查看malicious的匯編代碼,找到賦值語(yǔ)句對(duì)應(yīng)匯編的位置,并修改初值。注意倉(cāng)庫(kù)作者沒(méi)提到但很重要的一點(diǎn):這一步是和平臺(tái)有關(guān)的。這就是為什么需要編譯至少2次。
  3. 再編譯一次。因?yàn)闆](méi)有改動(dòng)到malicious函數(shù),所以它生成的匯編代碼也不會(huì)改變。

我在原有代碼的基礎(chǔ)上做了些微不足道的修改。首先看代碼:

#include <stdio.h>   // I/O
#include <windows.h> // Mem

// supposed malicious function
void malicious (void) {
    // i is always zero
    int i = 0;
    // thus this check is always fail
    // unless SMC changes this value
    if (i == 0x114514)
        // this is the malicious behavior
        printf ("I'm a malware i = %08x\n", i);
    else printf ("not malware i = %d\n", i);
}

// simple anti analysis function
BOOL anti_analysis() {
    return IsDebuggerPresent();
}

// page permission, as in the previous examples
void change_page (void *addr) {
    DWORD old;
    SYSTEM_INFO si;
    UINT64 _addr = (UINT64) addr;
    GetSystemInfo (&si);
    int page_size = si.dwPageSize;
    _addr -= (UINT64) addr % page_size;

    if (!VirtualProtect ( (PVOID) _addr, page_size, PAGE_EXECUTE_READWRITE, &old) )
        printf ("Error: %x\n", GetLastError() );

    return;
}

#define FUNC_ADJUST_OFFSET 0x08 // Function entry offset
#define INSTR_OFFSET 0x3        // instruction offset within the function
#define INSTR_DATA 0x114514          // new instruction bytes

// Program entry
int main() {
    // try first time
    // will be non-malicious
    malicious();

    //debug print
    printf ("PID %u\n", GetCurrentProcessId() );

    // anti-analysis trick
    if (!anti_analysis() ) {
        // SMC, as in the previous case
        void *func_addr = (char *) malicious + FUNC_ADJUST_OFFSET;
        change_page ( (void *) malicious);
        int *instruction = (int *) ( (char *) func_addr + INSTR_OFFSET);
        *instruction = INSTR_DATA;
    }

    // try second time
    // this time will be malicious
    malicious();

    return 0;
}

我們首先要編譯一次,查看malicious的匯編代碼:

.text:0000000000401550                               ; __int64 malicious(void)
.text:0000000000401550                               public _Z9maliciousv
.text:0000000000401550                               _Z9maliciousv proc near                 ; CODE XREF: main+D↓p
.text:0000000000401550                                                                       ; main:loc_40174D↓p
.text:0000000000401550                                                                       ; DATA XREF: main+46↓o
.text:0000000000401550                                                                       ; .pdata:000000000040506C↓o
.text:0000000000401550
.text:0000000000401550                               var_4= dword ptr -4
.text:0000000000401550
.text:0000000000401550 55                            push    rbp
.text:0000000000401551 48 89 E5                      mov     rbp, rsp
.text:0000000000401554 48 83 EC 30                   sub     rsp, 30h
.text:0000000000401558 C7 45 FC 00 00 00 00          mov     [rbp+var_4], 0
.text:0000000000401558
.text:000000000040155F
.text:000000000040155F                               loc_40155F:                             ; DATA XREF: main+3B↓o
.text:000000000040155F 83 7D FC 00                   cmp     [rbp+var_4], 0
.text:0000000000401563 74 13                         jz      short loc_401578
.text:0000000000401563
.text:0000000000401565 8B 45 FC                      mov     eax, [rbp+var_4]
.text:0000000000401568 89 C2                         mov     edx, eax
.text:000000000040156A 48 8D 0D 8F 2A 00 00          lea     rcx, Format                     ; "I'm a malware i = %d\n"
.text:0000000000401571 E8 CA 16 00 00                call    printf
.text:0000000000401571
.text:0000000000401576 EB 11                         jmp     short loc_401589
.text:0000000000401576
.text:0000000000401578                               ; ---------------------------------------------------------------------------
.text:0000000000401578
.text:0000000000401578                               loc_401578:                             ; CODE XREF: malicious(void)+13↑j
.text:0000000000401578 8B 45 FC                      mov     eax, [rbp+var_4]
.text:000000000040157B 89 C2                         mov     edx, eax
.text:000000000040157D 48 8D 0D 92 2A 00 00          lea     rcx, aNotMalwareID              ; "not malware i = %d\n"
.text:0000000000401584 E8 B7 16 00 00                call    printf

我們的目標(biāo)就是這句:.text:0000000000401558 C7 45 FC 00 00 00 00 mov [rbp+var_4], 0。于是可以修改代碼里定義的FUNC_ADJUST_OFFSETINSTR_OFFSET。修改好后再編譯一次即可看到效果。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-432774.html

參考資料

  1. https://www.cnblogs.com/rixiang/p/8954822.html
  2. https://www.cygwin.com/cygwin-ug-net/dll.html

到了這里,關(guān)于【reverse】手把手帶你基于dll實(shí)現(xiàn)多次SMC的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包