資源共享吧|易語言論壇|逆向破解教程|輔助開發(fā)教程|網(wǎng)絡(luò)安全教程|rigasin.com|我的開發(fā)技術(shù)隨記

 找回密碼
 注冊成為正式會員
查看: 2790|回復(fù): 2
打印 上一主題 下一主題

linux動(dòng)態(tài)注入(含視頻演示) 看雪大佬

[復(fù)制鏈接]

715

主題

1223

帖子

1

精華

終身高級VIP會員

Rank: 7Rank: 7Rank: 7

資源幣
11472
積分
4971
貢獻(xiàn)
0
在線時(shí)間
2065 小時(shí)
注冊時(shí)間
2015-4-20
最后登錄
2024-7-9

終身VIP會員

跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2018-10-3 13:37:59 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
linux動(dòng)態(tài)注入(含視頻演示) 看雪大佬



如果純粹用文字來描述什么是動(dòng)態(tài)注入,可能還是不太容易理解,所以本篇文章從如下一段代碼開始:
//who.c
#include <stdio.h>
#include <unistd.h>
int main()
{
while(1) {
printf("who are you ?\n");
sleep(2);
}
return0;
}
這段代碼本身沒有什么意思,執(zhí)行"gcc who.c -o who -g -Wall"完成編譯并啟動(dòng)who程序,每隔2s會向終端打印一句"who are you ?",但有意思的是,可能會出現(xiàn)一種"詭異"的現(xiàn)象,比如屏幕上突然冒出一句"it's me ~"。

1. 為什么可以出現(xiàn)這種“詭異”的現(xiàn)象?
通過反匯編who程序可以看出,程序最終會進(jìn)入while(1)循環(huán)體,重復(fù)執(zhí)行"bf24064000"、"e8c5feffff"、"bd0x000000"、"e8ebfeffff"、"ebea"這5條機(jī)器指令:





如果who進(jìn)程執(zhí)行到某條指令(比如"e8c5feffff")時(shí)暫停了,并且在恢復(fù)執(zhí)行之前,0x400586處的指令塊被替換成打印"it's me ~"的代碼,那么who進(jìn)程下次執(zhí)行,自然就會打印"it's me ~"。





2. 怎么獲取打印"it's me ~"的機(jī)器碼?
32位系統(tǒng),編譯如下代碼并在反匯編結(jié)果中提。
//isme32.c
int main()
{
__asm__(
"jmp forward\n\t"
"backward:popl %esi\n\t"
"movl $4, %eax\n\t"
"movl $2, %ebx\n\t"
"movl %esi, %ecx\n\t"
"movl $12, %edx\n\t"
"int $0x80\n\t"
"int3\n\t"
"forward:call backward\n\t"
".string \"it's me ~\\n\""
);
return0;
}
64位系統(tǒng),編譯如下代碼并在反匯編結(jié)果中提取:
//isme64.c
int main()
{
__asm__(
"jmp forward\n\t"
"backward:popq %rsi\n\t"
"movq $1, %rax\n\t"
"movq $2, %rdi\n\t"
"movq $12, %rdx\n\t"
"syscall\n\t"
"int3\n\t"
"forward:call backward\n\t"
".string \"it's me ~\\n\""
);
return0;
}
本篇文章的實(shí)驗(yàn)環(huán)境是64位ubuntu系統(tǒng),所以執(zhí)行"gcc isme64.c -oisme64 -g -Wall"生成isme64可執(zhí)行文件,并通過反匯編isme64文件提取機(jī)器碼:





用藍(lán)色、綠色標(biāo)記出來的16進(jìn)制內(nèi)容,即為打印"it's me ~"的機(jī)器碼,但有2點(diǎn)需要說明:
綠色部分其實(shí)是"it's me ~\n\0"這串字符的ascii碼值,也被objdump解釋成匯編指令了,這是反匯編工具很難避免的一個(gè)問題,用gdb/disassemble反匯編的結(jié)果也是一樣的,因?yàn)樗鼈冞x擇的都是線性掃描算法,遞歸下降算法效果會好一些,但仍然不能保證得到精確的結(jié)果;
C程序?qū)崿F(xiàn)打印"it's me ~",寫一條printf("it's me ~")語句不就可以了么,為什么要寫成這種"奇奇怪怪"的樣子?因?yàn)槿绻肅語法來實(shí)現(xiàn)的話,"it's me ~"這個(gè)字符串會被編譯器安排到isme64程序的.data段,就沒辦法隨著指令塊一起注入到目標(biāo)進(jìn)程中,而且這段代碼中取"it's me ~"地址的技巧,對于匯編初學(xué)者是很有意思的,代碼不長,建議在大腦里執(zhí)行一遍,并找到其中的奧妙。
3. 怎么實(shí)現(xiàn)注入?
本篇文章僅僅用于學(xué)習(xí)目的,注入的場景和方法都比較簡單,思路在文章第1節(jié)已經(jīng)介紹過了,就是"暫停被注入進(jìn)程 -> 替換即將執(zhí)行的指令塊 -> 通知被注入進(jìn)程繼續(xù)執(zhí)行",由于有些場合還需要保證注入操作的隱蔽性,所以以下程序還在注入指令塊完整執(zhí)行后,將被注入進(jìn)程恢復(fù)到了注入前的狀態(tài):
(理解這段代碼,至少需要學(xué)習(xí)ptrace()系統(tǒng)調(diào)用的作用,如果有內(nèi)核基礎(chǔ),也可以更深入的學(xué)習(xí)一下ptrace()的內(nèi)部原理,另外,CODE宏對應(yīng)的內(nèi)容,即為利用文章第2節(jié)描述的方法,提取的機(jī)器碼)
// inject.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <errno.h>


// 注入指令塊(打印"it's me ~")
#ifdef ENV_I386
#define CODE \
    "\xeb\x15\x5e\xb8\x04\x00\x00\x00"\
    "\xbb\x02\x00\x00\x00\x89\xf1\xba"\
    "\x0c\x00\x00\x00\xcd\x80\xcc\xe8"\
    "\xe6\xff\xff\xff\x69\x74\x27\x73"\
    "\x20\x6d\x65\x20\x7e\x0a\x00"
#define REG_IP  regs.eip
#else   // X_64
#define CODE \
    "\xeb\x19\x5e\x48\xc7\xc0\x01\x00"\
    "\x00\x00\x48\xc7\xc7\x02\x00\x00"\
    "\x00\x48\xc7\xc2\x0c\x00\x00\x00"\
    "\x0f\x05\xcc\xe8\xe2\xff\xff\xff"\
    "\x69\x74\x27\x73\x20\x6d\x65\x20"\
    "\x7e\x0a\x00"
#define REG_IP  regs.rip
#endif

#define CODE_SIZE (sizeof(CODE)-1)


/* 往pid進(jìn)程的addr地址處寫數(shù)據(jù) */
voidputdata(pid_t pid, unsigned longaddr, void*vptr, intlen)
{
    intcount = 0;
    longword;

    while(count < len)
    {
        memcpy(&word, vptr+count, sizeof(word));
        word = ptrace(PTRACE_POKEDATA, pid, addr+count, word);
        count += sizeof(word);

        if(errno!= 0)
            printf("putdata failed: %p\n", (void*)(addr+count));
    }
}

/* 讀pid進(jìn)程addr地址處的數(shù)據(jù) */
voidgetdata(pid_t pid, unsigned longaddr, void*vptr, intlen)
{
    inti = 0, count = 0;
    longword;
    unsigned long*ptr = (unsigned long*)vptr;

    while(count < len)
    {
        word = ptrace(PTRACE_PEEKDATA, pid, addr+count, NULL);
        count += sizeof(word);
        ptr[i++]  = word;

        if(errno!= 0)
            printf("getdata failed: %p\n", (void*)(addr+count));
    }
}


intmain(intargc, char*argv[])
{
    pid_t pid;
    structuser_regs_struct regs;
    charbackup[CODE_SIZE+1];

    if(argc != 2) {
        printf("Usage: %s {pid}\n", argv[0]);
        return-1;
    }

    // 通過啟動(dòng)參數(shù),獲取被注入進(jìn)程號,并attach
    pid = atoi(argv[1]);
    ptrace(PTRACE_ATTACH, pid, NULL, NULL);  // SIGTRAP
    if(errno!= 0)
        printf("attach failed: %s\n", strerror(errno));
    wait(NULL);  // 收到回復(fù)信號,保證后續(xù)過程在attach完成的情況下執(zhí)行

    // 獲取被注入進(jìn)程當(dāng)前寄存器值
    ptrace(PTRACE_GETREGS, pid, NULL, &#174;s);
    // 備份*ip寄存器指向的指令塊
    getdata(pid, REG_IP, backup, CODE_SIZE);
    // 替換為CODE指令塊
    putdata(pid, REG_IP, CODE, CODE_SIZE);
    // 恢復(fù)被注入進(jìn)程的執(zhí)行
    ptrace(PTRACE_CONT, pid, NULL, NULL);    // SIGCONT
    // 注入程序最后一條指令為int3,此為即為等待注入指令塊執(zhí)行完畢
    wait(NULL);

    // 等待用戶輸入,方便查看結(jié)果
    printf("continue to execute the orginal process, press any key ..\n");
    getchar();

    // 將修改的指令塊恢復(fù)為備份內(nèi)容
    putdata(pid, REG_IP, backup, CODE_SIZE);
    // 恢復(fù)被注入進(jìn)程寄存器值
    ptrace(PTRACE_SETREGS, pid, NULL, &#174;s);

    // detach,被注入進(jìn)程恢復(fù)正常執(zhí)行
    ptrace(PTRACE_DETACH, pid, NULL, NULL);

    return0;
}

4. 視頻演示
a. 執(zhí)行g(shù)cc inject.c -oinject -g -Wall,編譯生成注入程序
b. 查看who進(jìn)程號N,并執(zhí)行sudo inject N,進(jìn)行動(dòng)態(tài)注入操作
c. 觀察who程序執(zhí)行窗口是否打印了"it's me ~"
d. 回到inject程序執(zhí)行窗口,按任意鍵結(jié)束inject進(jìn)程,并恢復(fù)who進(jìn)程到注入前的狀態(tài),繼續(xù)不停的打印"who are you ?"

視頻鏈接:https://v.youku.com/v_show/id_XMzgzMTM1NTU1Ng==.html?spm=a2h0k.11417342.soresults.dposter






回復(fù)

使用道具 舉報(bào)

4

主題

73

帖子

0

精華

終身高級VIP會員

Rank: 7Rank: 7Rank: 7

資源幣
151
積分
141
貢獻(xiàn)
0
在線時(shí)間
14 小時(shí)
注冊時(shí)間
2018-2-26
最后登錄
2022-7-11

終身VIP會員

沙發(fā)
發(fā)表于 2018-10-3 17:27:51 | 只看該作者
先圍觀看看

0

主題

51

帖子

0

精華

注冊會員

Rank: 2

資源幣
5
積分
51
貢獻(xiàn)
0
在線時(shí)間
3 小時(shí)
注冊時(shí)間
2024-8-23
最后登錄
2024-8-28
板凳
發(fā)表于 2024-8-27 14:17:18 | 只看該作者
不明覺厲
回復(fù)

使用道具 舉報(bào)

 點(diǎn)擊右側(cè)快捷回復(fù)  

本版積分規(guī)則

小黑屋|資源共享吧 ( 瓊ICP備2023000410號-1 )

GMT+8, 2025-4-18 16:47 , Processed in 0.053482 second(s), 14 queries , MemCached On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回復(fù) 返回頂部 返回列表