有趣的二進制-逆向工程

體驗一下軟件分析

  1. 常用的分析工具
  • Stirling-二進制編輯器
  • Process Monitor-文件和註冊表監控
  • Wireshark-網絡監控
  1. 運行chap01\sample_mal\Release目錄中的sample_mal.exe文件,運行後會彈出一個對話框:
    在這裏插入圖片描述
  2. 通過Process Monitor的日誌來確認程序的行爲
  • 點擊Filter
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 通過跟蹤Process Monitor的日誌,我們可以發現程序在C:\Users\alice\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup位置進行了CreateFile的操作。
  • 存放在啓動文件夾中的程序,會隨着windows啓動自動運行。
  • 示例程序連續執行CreateFile、WriteFile和CloaseFile幾個操作,這些操作加起來的功能相當於“在指定文件夾創建並寫入一個名爲0.exe的文件”。
    在這裏插入圖片描述
  • 用Stirling打開0.exe和sample_mal.exe程序,查看其二進制代碼:
    在這裏插入圖片描述
  • 可以看到兩者的內容完全一致,sample_exe只是將自己拷貝了一份。

查看註冊表(win10下寫入註冊表顯示權限拒絕)

  1. 註冊表是Windows系統提供的一個用於保存配置信息的數據庫,其中保存的數據包括瀏覽器設置、文件類型關聯、用戶密碼等。
  2. 進一步分析日誌,我們發現程序想要往註冊的Run目錄下寫入一個文件。
  3. 計算機\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run和啓動文件夾一樣,其中註冊的程序會在Windows重啓時自動運行。
  4. Windows重啓時自動運行的程序可以註冊在下列任一註冊表的位置:
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
  • HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion
  1. 此時我們還發現,在文檔目錄文件夾下還創建了一個名爲1.exe的文件
    在這裏插入圖片描述
  • 和0.exe一樣,1.exe也是sample_mal.exe的一個副本
  • 1.exe的路徑已經被註冊在註冊表下面,HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Current Version\Run,Windows啓動時就會自動運行1.exe。
  • 查看註冊表內容window+R->regedit
  • sample.exe只會彈出一個Hello Malware的對話框,並沒有進行任何操作。我們只要將“啓動”文件夾、“我的文檔”以及註冊表中新增的內容刪除,系統環境就可以完全恢復原狀了。

什麼是逆向工程

  1. sample_mal.exe程序會執行以下操作:
  • 修改註冊表以便系統重啓時自動運行
  • 將自己複製到啓動文件夾以便在系統重啓時自動運行
  1. 對於上面這樣軟件進行分析並搞清楚其行爲的工作就是逆向工程,逆向工程是指一般意義上的軟件分析,其對象不僅限於惡意軟件,因此也不一定和計算機安全相關。
  2. 逆向工程原本是指通過拆解機器裝置並觀察其運行情況來推導其製造方法、工作原理和原始設計的行爲,但是在軟件領域,逆向工程主要指的是閱讀反彙編後的代碼,以及使用調試器分析軟件行爲等工作。

嘗試靜態分析

  1. 軟件分析方法上大體可以分爲“靜態分析”和“動態分析”兩種:
  • 靜態分析:在不運行目標程序的情況下進行分析
  • 動態分析:在運行目標程序的同時進行分析
  1. 靜態分析主要包括以下兩種方法:
  • 閱讀反彙編代碼
  • 提取可執行文件中的字符串,分析使用了哪些單詞。
  1. 對chap01\wsample01a\Release\wsample01.exe進行靜態分析,wsample01a.exe的運行結果如下所示:
    在這裏插入圖片描述
  2. 用二進制編輯器查看文件內容
    在這裏插入圖片描述
  • 屏幕上顯示一串十六進制字符,這就是Windows可執行文件格式,即“PE格式“的文件內容。
  • 我們能夠發現下面這些內容

字符串MESSAGE和Hello!Windows
文件路徑C:\Documents and Settings\XPMUser…
字符串KERNEL32.dll、MessageBoxW

  1. 使用IDA PRO來進行反彙編分析
  • 打開wsample01.exe文件
    在這裏插入圖片描述
  • 左鍵顯示的是程序使用的所有函數名稱,右側可以點擊空格在Text View或Graph View視圖中進行切換。
  • 在Graph View視圖中IDA會顯示出調出的函數以及傳遞的參數。
  1. wWinMain函數裏面的邏輯除了Hello!Windows、MESSAGE、MessageBoxW等字符串外,還包含:
  • 2012
  • lstrcmpW
  • GetActiveWindow
  1. Hello!Windows和Hello!2012這兩個字符串實在不同的條件分支中顯示的。
  2. 通過命令行輸入2012作爲參數來運行一下wsample01a.exe程序:
    在這裏插入圖片描述
  • 只要閱讀了彙編語言代碼,就可以發現其中使用了lstrcmoW對字符串2012和命令行參數進行了比較操作。
    在這裏插入圖片描述
  • 查看wsample01.cpp的真正源代碼:
int APIENTRY _tWinMain(
	HINSTANCE hInstance, 
	HINSTANCE hPrevInstance, 
	LPTSTR    lpCmdLine, 
	int       nCmdShow)
{
	if(lstrcmp(lpCmdLine, _T("2012")) == 0){
		MessageBox(GetActiveWindow(), 
			_T("Hello! 2012"), _T("MESSAGE"), MB_OK);
	}else{
		MessageBox(GetActiveWindow(), 
			_T("Hello! Windows"), _T("MESSAGE"), MB_OK);
	}	
	return 0;
}
  • 通過IDA就可以將執行文件轉換成C語言一樣容易理解的彙編代碼,尤其是它的Graph view十分強大,可以讓我們十分清晰地看出程序的分支邏輯。

嘗試動態分析

  1. 動態分析是在目標程序運行的同時跟蹤其行爲的方法,主要使用調試器來跟蹤程序邏輯,除此之外,下面這些方法也被爲動態分析:
  • 獲取文件和註冊表訪問日誌
  • 抓取網絡包
  1. 開始分析一下chap01\wsample01b\Release的示例程序wsample01b.exe.
    在這裏插入圖片描述
  2. 使用Process monitor來查看wsample01b.exe文件和註冊表的訪問日誌:
    在這裏插入圖片描述
  • 可以看到wsample01b.exe在啓動目錄複製了一個自身的拷貝
  1. 調試器是一種幫助發現程序問題和bug的軟件,一般來說至少具備以下功能:
  • 斷點
  • 單步跳入、跳出
  • 查看寄存器和內存數據
  1. 斷點能夠在任意位置中斷和恢復運行,而每執行一條指令都中斷一次就叫作單步跳入或跳出。通過單步運行功能,我們可以以一條指令或者一行代碼爲單位逐個運行程序中的邏輯,仔細檢查內存和變量的狀態,跳入和跳出的區別:
  • 跳入:調用函數時進入函數內部
  • 跳出:調用函數時不進入函數內部,而是將函數調用作爲一條指令來執行。
  1. 將wsample01b.exe拖拽到OllyDbg中
  2. OllyDbg的畫面主要包括以下幾個部分:
  • 左上:主要反彙編窗口
  • 左下:內存數據窗口
  • 右上:寄存器
  • 右下:當前棧
  1. 按下Ctrl+G輸入地址00401000,然後跳轉到該指令對應的地址:
    在這裏插入圖片描述在這裏插入圖片描述
  2. 我們發現程序一次調用了GetModuleFileNameW、SHGetFolderPathW、lstrcatW、CopyFileW這幾個函數。
  3. 剛纔我們用Process Monitor已經發現程序會向“啓動”文件夾複製文件,我們可以推測“上面的CopyFile函數就是用來執行這一操作”。
  4. 首選選中地址00401000所在的行,然後按F2鍵,00401000的背景會變紅,說明我們已經在此位置設置了一個斷點。
  5. 接下來按下F9鍵,或者在窗口上方菜單點擊Debug->Run。這時,OllyDbg會啓動wasmple01b.exe,當到達斷點所在的位置00401000位置時,程序會暫停運行。
  6. 我們可以通過單步運行,逐條運行程序中的指令,按F7表示單步跳入,按F8表示單步跳出。
  7. 隨着每次按下F8,程序都會執行一條指令,同時右上方的寄存器窗口和右下方的堆棧窗口的內容也會發生變化。
  8. 讓程序一直運行到00401062的地方,也就是調用CopyFileW之前的位置,通過寄存器窗口和堆棧窗口,我們可以看到要複製的文件源路徑和目標路徑。
    在這裏插入圖片描述
  9. 如果我們再次按下F8鍵,程序就會調用CopyFileW函數,現在再看一下啓動文件夾。
    在這裏插入圖片描述
  10. 什麼是寄存器
  • 寄存器時位於CPU內部的存儲空間,每個寄存器都有自己的名字,分別叫做EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI、EIP。
  • ESP和EBP用於管理堆棧,而EIP則指向當前執行的指令
  • OllyDbg右上方的寄存器窗口中會顯示當前所有寄存器的值。
    在這裏插入圖片描述
  • 如果我們在OllyDbg中按下F8或者F7,程序就會執行一條指令,這是我們可以看到EIP的值會根據所執行指令的長度不斷增加。
  • EIP的下方還有C、P、A、Z、S、T、D、O這幾個字母,它們代表標誌,一般我們會在這些字母后面加上一個字母F(Flag的首字母),寫作CF、PF、AF、ZF,這些標誌主要用於條件分支,比如:

若ZF=1則跳轉。
若CF爲1則不跳轉。

  1. 程序源代碼
int cpy(void)
{
	// 獲取自身文件路徑
	TCHAR szThis[2048];
	GetModuleFileName(NULL, szThis, sizeof(szThis));
	// 獲取啓動文件夾路徑
	SHGetFolderPath(NULL, CSIDL_STARTUP, 
		NULL, SHGFP_TYPE_CURRENT, szStartup);
	lstrcat(szStartup, _T("\\wsample01b.exe"));
	// 將自身複製到啓動文件夾	
	CopyFile(szThis, szStartup, FALSE);
	return 0;
}

int APIENTRY _tWinMain(
	HINSTANCE hInstance, 
	HINSTANCE hPrevInstance, 
	LPTSTR    lpCmdLine, 
	int       nCmdShow)
{
	cpy();
	MessageBox(GetActiveWindow(), 
		_T("Copied!"), _T("MESSAGE"), MB_OK);
	return 0;
}
  1. 在進行軟件分析的時候一般使用Stirling和IDA看一下整體的樣子,然後再用OllyDbg的單步運行來查看一些特別關注的點。

學習彙編指令

  1. 常用匯編指令
  • MOV EAX,ECX;將ECX的值存入EAX
  • ADD EAX,ECX; EAX+=ECX
  • SUB EAX,ECX; EAX-=ECX
  • INC EAX; EAX++
  • DEC EAX;EAX–
  • LEA EAX,[ECX+4]; 將ECX+4的值存入EAX
  • CMP EAX,ECX; 對兩個值比較根據結果設置標誌,EAX=ECX,ZF=1;EAX!=ECX,ZF=0.
  • TEST EAX,EAX;將值與0比較並根據結果設置標註,EAX=0,ZF=1;EAX!=0,ZF=0;
  • JE(JZ) 04001000;若ZF=1,則跳轉到04001000
  • JNE(JNZ) 04001000;若ZF=0,跳轉到0400100
  • JMP 04001000;無條件跳轉到0400100
  • CALL lstrcmp;調用lstrcmpW
  • PUSH 00000001;將00000001入棧
  • POP EAX;出棧並將獲取的值存入EAX
  1. 彙編語言如何實現條件分支的
  • 彙編語言中,則是通過控制標誌的cmp、test指令,以及根據標誌完成分支的跳轉指令來實現的。
  • 在wsample01.exe中有個判斷的邏輯,如果命令行傳入參數2012,會顯示不同的消息。
    在這裏插入圖片描述
  • 其中在0040101B的地方出現一個jnz指令,這就是分支指令。
  • test eax,eax;意思就是當eax爲0時將ZF置爲1,大多數情況下test指令都會跟着兩個相同的寄存器名稱,可以簡單理解爲“若寄存器值爲0,則將ZF置爲1”。
  • jnz指令的意思就是,ZF=0時則進行跳轉,將jnz指令和test指令結合起來就實現了下面的邏輯:

若eax爲0則不跳轉
若eax爲1則跳轉

  • eax使0040100C的call lstrcmpW的返回值
  1. 參數存放在棧中
  • call指令是用來調用子程序的,它的返回值被存放在eax中。
  • 子程序的調用可以理解爲下面的過程:
function(1,2,3);
//對應彙編代碼
push 3
push 2
push 1
call function
  • 在彙編語言中,參數時按照從後往前的順序入棧,其實這這方面的規則會根據CPU和編譯器的不同而存在一些差異。
  • 例如,00401006內存位置對應的代碼:
    在這裏插入圖片描述
  • 對應代碼 eax = lstrcmpW(eax,“2012”);
  • lstrcmpW函數功能是,當參數中的兩個字符串相同時,則返回0,否則返回非0;
    在這裏插入圖片描述
  • 00401019的test指令表示若eax爲0則將ZF置爲1,0040101B的jnz指令表示當ZF=0時跳轉。因此,當ZF=1時程序不會進行跳轉,而是繼續執行0040101D的指令,結果就顯示出了Hello!2012這條消息。

從彙編代碼聯想到C語言代碼

  1. 再來查看以下wsample01b.exe彙編代碼
.text:00401000 Filename        = word ptr -2004h
.text:00401000 pszPath         = word ptr -1004h
.text:00401000 var_4           = dword ptr -4
.text:00401000
.text:00401000                 push    ebp
.text:00401001                 mov     ebp, esp
.text:00401003                 mov     eax, 2004h
.text:00401008                 call    __alloca_probe
.text:0040100D                 mov     eax, ___security_cookie
.text:00401012                 xor     eax, ebp
.text:00401014                 mov     [ebp+var_4], eax
.text:00401017                 push    1000h           ; nSize
.text:0040101C                 lea     eax, [ebp+Filename]
.text:00401022                 push    eax             ; lpFilename
.text:00401023                 push    0               ; hModule
.text:00401025                 call    ds:GetModuleFileNameW
.text:0040102B                 lea     ecx, [ebp+pszPath]
.text:00401031                 push    ecx             ; pszPath
.text:00401032                 push    0               ; dwFlags
.text:00401034                 push    0               ; hToken
.text:00401036                 push    7               ; csidl
.text:00401038                 push    0               ; hwnd
.text:0040103A                 call    ds:SHGetFolderPathW
.text:00401040                 push    offset String2  ; "\\wsample01b.exe"
.text:00401045                 lea     edx, [ebp+pszPath]
.text:0040104B                 push    edx             ; lpString1
.text:0040104C                 call    ds:lstrcatW
.text:00401052                 push    0               ; bFailIfExists
.text:00401054                 lea     eax, [ebp+pszPath]
.text:0040105A                 push    eax             ; lpNewFileName
.text:0040105B                 lea     ecx, [ebp+Filename]
.text:00401061                 push    ecx             ; lpExistingFileName
.text:00401062                 call    ds:CopyFileW
.text:00401068                 mov     ecx, [ebp+var_4]
.text:0040106B                 xor     ecx, ebp
.text:0040106D                 xor     eax, eax
.text:0040106F                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:00401074                 mov     esp, ebp
.text:00401076                 pop     ebp
.text:00401077                 retn
.text:00401077 sub_401000      endp
.text:00401077
.text:00401077 ; ---------------------------------------------------------------------------
.text:00401078                 align 10h
.text:00401080
.text:00401080 ; =============== S U B R O U T I N E =======================================
.text:00401080
.text:00401080
.text:00401080 ; int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
.text:00401080 _wWinMain@16    proc near               ; CODE XREF: ___tmainCRTStartup+153↓p
.text:00401080
.text:00401080 hInstance       = dword ptr  4
.text:00401080 hPrevInstance   = dword ptr  8
.text:00401080 lpCmdLine       = dword ptr  0Ch
.text:00401080 nShowCmd        = dword ptr  10h
.text:00401080
.text:00401080                 call    sub_401000
.text:00401085                 push    0               ; uType
.text:00401087                 push    offset Caption  ; "MESSAGE"
.text:0040108C                 push    offset Text     ; "Copied!"
.text:00401091                 call    ds:GetActiveWindow
.text:00401097                 push    eax             ; hWnd
.text:00401098                 call    ds:MessageBoxW
.text:0040109E                 xor     eax, eax
.text:004010A0                 retn    10h
.text:004010A0 _wWinMain@16    endp
  • 在cpy函數開頭的fileName、pszPath、var_4都是函數使用的局部變量。
  • lea eax, [ebp+Filename]中有個ebp+Filename就是將Filename的地址放入eax中。
  • 對應C語言應該時下面:
char fileName[2048];
eax=finName;

通過彙編指令洞察程序行爲

  1. 使用OllyDbg打開sample_mal.exe,然後在反彙編窗口點擊右鍵,選擇:
    在這裏插入圖片描述
  • 從顯示出的函數列表中找到類型爲Export的RgesetValueExA函數,OllyDbg支持通過鍵盤快速查找,只要輸入RegSetV…就可以定位到目標函數了。
    在這裏插入圖片描述
  • 雙擊函數就可以就會跳轉到該函數的開頭,接下來在下列函數位置處設置斷點:

RegSetValueExA
RegSetValueExA
RegCreateKeyExA
CopyFileA

  • 上面的目標函數各有兩種類型:一種是Export;另一種是Import,選擇類型爲Export的函數上雙擊被設置斷點。
  • RegSetValueExA、RegSetValueExA、 RegCreateKeyExA位於ADVAPI32模塊中,而CopyFileA位於kernel32模塊中。
  • 設置好斷點後,點擊F9運行程序,程序會在斷點處暫停運行
  • 按Ctrl+F9程序會繼續運行到函數返回的地方
  • CopyFileA函數返回的地方
    在這裏插入圖片描述
  1. 反彙編並觀察重要邏輯
  • 使用IDA打開sample_mal.exe,來看看複製0.exe和1.exe的地方
    在這裏插入圖片描述
  • 00401452處的代表SetRegValue函數,0040145A代表selDelete函數,它們分別用來設置註冊表以及將自身刪除。
  • 查看SetRegValue函數:
.text:00401310
.text:00401310 dwDisposition   = dword ptr -8
.text:00401310 phkResult       = dword ptr -4
.text:00401310 lpData          = dword ptr  8
.text:00401310 cbData          = dword ptr  0Ch
.text:00401310
.text:00401310                 push    ebp
.text:00401311                 mov     ebp, esp
.text:00401313                 sub     esp, 8
.text:00401316                 push    esi
.text:00401317                 lea     eax, [ebp+dwDisposition]
.text:0040131A                 push    eax             ; lpdwDisposition
.text:0040131B                 xor     esi, esi
.text:0040131D                 lea     ecx, [ebp+phkResult]
.text:00401320                 push    ecx             ; phkResult
.text:00401321                 push    esi             ; lpSecurityAttributes
.text:00401322                 push    0F003Fh         ; samDesired
.text:00401327                 push    esi             ; dwOptions
.text:00401328                 push    offset Class    ; lpClass
.text:0040132D                 push    esi             ; Reserved
.text:0040132E                 push    offset SubKey   ; "Software\\Microsoft\\Windows\\CurrentVe"...
.text:00401333                 push    80000002h       ; hKey
.text:00401338                 mov     [ebp+phkResult], esi
.text:0040133B                 call    ds:RegCreateKeyExA
.text:00401341                 test    eax, eax
.text:00401343                 jnz     short loc_401370
.text:00401345                 mov     edx, [ebp+cbData]
.text:00401348                 mov     eax, [ebp+lpData]
.text:0040134B                 mov     ecx, [ebp+phkResult]
.text:0040134E                 push    edx             ; cbData
.text:0040134F                 push    eax             ; lpData
.text:00401350                 push    1               ; dwType
.text:00401352                 push    esi             ; Reserved
.text:00401353                 push    offset ValueName ; "sample_mal"
.text:00401358                 push    ecx             ; hKey
.text:00401359                 call    ds:RegSetValueExA
.text:0040135F                 test    eax, eax
.text:00401361                 jnz     short loc_401366
.text:00401363                 lea     esi, [eax+1]
.text:00401366
.text:00401366 loc_401366:                             ; CODE XREF: sub_401310+51↑j
.text:00401366                 mov     edx, [ebp+phkResult]
.text:00401369                 push    edx             ; hKey
.text:0040136A                 call    ds:RegCloseKey
.text:00401370
.text:00401370 loc_401370:                             ; CODE XREF: sub_401310+33↑j
.text:00401370                 mov     eax, esi
.text:00401372                 pop     esi
.text:00401373                 mov     esp, ebp
.text:00401375                 pop     ebp
.text:00401376                 retn
.text:00401376 sub_401310      endp
  • 查看SelfDelete函數:
.text:00401220 sub_401220      proc near               ; CODE XREF: sub_401380+DA↓p
.text:00401220
.text:00401220 String1         = byte ptr -20Ch
.text:00401220 Filename        = byte ptr -108h
.text:00401220 var_4           = dword ptr -4
.text:00401220
.text:00401220                 push    ebp
.text:00401221                 mov     ebp, esp
.text:00401223                 sub     esp, 20Ch
.text:00401229                 mov     eax, ___security_cookie
.text:0040122E                 xor     eax, ebp
.text:00401230                 mov     [ebp+var_4], eax
.text:00401233                 push    104h            ; nSize
.text:00401238                 lea     eax, [ebp+Filename]
.text:0040123E                 push    eax             ; lpFilename
.text:0040123F                 push    0               ; hModule
.text:00401241                 call    ds:GetModuleFileNameA
.text:00401247                 test    eax, eax
.text:00401249                 jz      loc_4012F3
.text:0040124F                 push    104h            ; cchBuffer
.text:00401254                 lea     ecx, [ebp+Filename]
.text:0040125A                 push    ecx             ; lpszShortPath
.text:0040125B                 mov     edx, ecx
.text:0040125D                 push    edx             ; lpszLongPath
.text:0040125E                 call    ds:GetShortPathNameA
.text:00401264                 test    eax, eax
.text:00401266                 jz      loc_4012F3
.text:0040126C                 push    esi
.text:0040126D                 push    offset aCDel    ; "/c del "
.text:00401272                 lea     eax, [ebp+String1]
.text:00401278                 push    eax             ; lpString1
.text:00401279                 call    ds:lstrcpyA
.text:0040127F                 mov     esi, ds:lstrcatA
.text:00401285                 lea     ecx, [ebp+Filename]
.text:0040128B                 push    ecx             ; lpString2
.text:0040128C                 lea     edx, [ebp+String1]
.text:00401292                 push    edx             ; lpString1
.text:00401293                 call    esi ; lstrcatA
.text:00401295                 push    offset aNul     ; " >> NUL"
.text:0040129A                 lea     eax, [ebp+String1]
.text:004012A0                 push    eax             ; lpString1
.text:004012A1                 call    esi ; lstrcatA
.text:004012A3                 push    104h            ; nSize
.text:004012A8                 lea     ecx, [ebp+Filename]
.text:004012AE                 push    ecx             ; lpBuffer
.text:004012AF                 push    offset Name     ; "ComSpec"
.text:004012B4                 call    ds:GetEnvironmentVariableA
.text:004012BA                 pop     esi
.text:004012BB                 test    eax, eax
.text:004012BD                 jz      short loc_4012F3
.text:004012BF                 push    0               ; nShowCmd
.text:004012C1                 push    0               ; lpDirectory
.text:004012C3                 lea     edx, [ebp+String1]
.text:004012C9                 push    edx             ; lpParameters
.text:004012CA                 lea     eax, [ebp+Filename]
.text:004012D0                 push    eax             ; lpFile
.text:004012D1                 push    0               ; lpOperation
.text:004012D3                 push    0               ; hwnd
.text:004012D5                 call    ds:ShellExecuteA
.text:004012DB                 cmp     eax, 20h
.text:004012DE                 jle     short loc_4012F3
.text:004012E0                 mov     eax, 1
.text:004012E5                 mov     ecx, [ebp+var_4]
.text:004012E8                 xor     ecx, ebp
.text:004012EA                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:004012EF                 mov     esp, ebp
.text:004012F1                 pop     ebp
.text:004012F2                 retn
  1. 學習編寫彙編代碼
  • 安裝NSAM彙編器,連接器ALINK
  • 新建一個文件,拓展名改爲asm
extern MessageBoxA

section .text
global main

main:
         push dword 0
         push dword title
         push dword text
         push dword 0
         call MessageBoxA
         ret

section .data
title: db 'MessageBox', 0
text: db  'Hello World!', 0
  • MessageBoxA需要以下4個參數

父窗口句柄
要顯示的消息
要顯示的消息框標題
要顯示的消息框類型

  • 函數調用過程:

要顯示的消息:Hello World!
要顯示的標題:MessageBox
將參數按照從後往前的順序入棧
用call MessageBoxA調用函數

  • 用NASM加上-fwin32參數將代碼彙編爲.obj文件
  • 用Alink生產可執行文件
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章