0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

C/C++之函數(shù)體hack(上)

jf_78858299 ? 來源:小余的自習室 ? 作者:小余的自習室 ? 2023-03-30 16:54 ? 次閱讀

前言

首先來說下 什么是hack ? hack字面意思“ 非法入侵 ”,那么在C/C++中其實就是 使用反匯編查看C/C++代碼對應的匯編代碼

那可能有人要問了,C/C++不是高級語言么,為什么還要看匯編代碼?理由嘛見仁見智,

個人理解有下面幾種:

  • 1.C/C/C++應用不像java,python那樣,報錯信息可以在日志中一目了然,C/C++應用的報錯可以讓你查的懷疑人生,為什么呢?因為 報錯日志提供的信息可能會誤導你 ,比如真實錯誤是在100行,但是報錯信息會在第一行或者全局都有報錯,就很讓人上頭。。有了這個hack過程,就可以定位到可能報錯的地方,使用hack反編譯得到匯編代碼,匯編代碼可以讓你看清你寫的C/C/C++代碼對于CPU來說實際執(zhí)行的行為。
  • 2.當我們在調(diào)試C/C++應用的時候,經(jīng)常會 有些疑惑 ,比如i++和++i為什么結果不同,又比如inline內(nèi)聯(lián)函數(shù)有什么用處?原理是什么?等等,這些也可以使用hack來解釋,那有人要說了,這些我都知道啥意思啊,i++和++i前自增和后自增么,內(nèi)聯(lián)函數(shù)原理就是編譯期將函數(shù)代碼拷貝到調(diào)用處嘛。可是這些都是別人告訴你的,那如果一個代碼段別人沒告訴你呢?百度是不是什么都可以找到的,特別是對于C/C++開發(fā)來說,信息更是少的可憐,此時你就會知道hack是多重要了。
  • 3.如果你的C/C++應用需要實現(xiàn)一些性 能上優(yōu)化 ,也可以使用hack過程查看CPU和內(nèi)存的行為,從而對應用性能做一些提升,是不是很cool。。

既然有這么多用處,那么下面小余就來講解下如何在我們的應用中hack。

不過在hack前我們需要了解一些匯編語言基礎。

匯編語言基礎

首先我們得了解匯編語言中的幾個模塊:1.寄存器 2.內(nèi)存 3.CPU

1.寄存器

寄存器是我們計算機中的最小存儲單位,在計算機金字塔的頂端, 屬于CPU的內(nèi)部存儲 ,主要用來存儲CPU需要使用到的臨時數(shù)據(jù)。

CPU訪問寄存器的速度比訪問內(nèi)存的速度快了100倍左右。

CPU中寄存器種類包括:通用寄存器,指令地址寄存器,狀態(tài)寄存器等等等等。。 這里只介紹幾個比較關鍵的寄存器:

1.通用寄存器

寄存器 原文 解釋 說明
AX accumulator 累加寄存器 通常用來執(zhí)行加法,函數(shù)調(diào)用的返回值一般也放在這里面
CX counter 計數(shù)寄存器 通常用來作為計數(shù)器,比如for循環(huán)
DX data 數(shù)據(jù)寄存器 數(shù)據(jù)存取
BX base 基址寄存器 讀寫I/O端口時,edx用來存放端口號
SP stack pointer 棧指針寄存器 棧頂指針,指向棧的頂部
BP base pointer 基址指針寄存器 棧底指針,指向棧的底部,通常用ebp+偏移量的形式來定位函數(shù)存放在棧中的局部變量
SI source index 源變址寄存器 字符串操作時,用于存放數(shù)據(jù)源的地址
DI destination index 目標變址寄存器 字符串操作時,用于存放目的地址的,和esi兩個經(jīng)常搭配一起使用,執(zhí)行字符串的復制等操作

這里說明幾點:

  • 1.在具體hack的過程中你可能看到的是eax,ecx,edx等而不是AX,CX,DX,他們區(qū)別: 帶e開頭的說明是32位寄存器,也就是4個字節(jié)存儲的寄存器,而AX是eax的低16位的“子寄存器”, 這是早期一些寄存器是16位的,而為了兼容早期這些寄存器就使用“子寄存器”來標識。
  • 2.匯編語言中,在函數(shù)體返回時,統(tǒng)一使用eax為返回值,這個為什么這樣?我也不清楚,可能是早期大家都這么用就約定下來了吧。
  • 3.當我們在使用函數(shù)的時候,會將ebp的內(nèi)容壓入棧底,作為棧底指針,指向棧的底部,局部變量使用ebp+偏移地址來定位。對于棧頂則使用esp寄存器來定位,關于函數(shù)棧會在后面講解。

2.eip寄存器

eip寄存器可以說是CPU中最關鍵的一個寄存器了,它指向了下一條要執(zhí)行的指令所存放的地址, CPU工作其實就是取出eip中的地址中的指令,然后去執(zhí)行這條指令,并將下一條指令的地址賦值給eip ,這樣CPU就可以依次執(zhí)行完成所有的匯編代碼.

如果你要問我它是怎么找到下一條指令的地址的,首先正常執(zhí)行指令是+1位下一條指令地址,如果碰到一些比如if語句,函數(shù)調(diào)用等情況,就會在上一條指令中得到這個地址,并賦值給eip,這個賦值動作是CPU自動完成的,開發(fā)是不能隨便更改的,這也變相的防止你搞出bug不是?

3.狀態(tài)寄存器

狀態(tài)寄存器中記錄了CPU執(zhí)行過程中的一系列狀態(tài),對于32位就有32個標志位,這些標志大部分都是由CPU自行設置:

寄存器標志位 解釋
CF 進位標志
PF 奇偶標志
ZF 零標志
SF 符號標志
OF 補碼溢出標志
TF 跟蹤標志
IF 中斷標志
……

圖片

4.指令寄存器:

根據(jù)指令在存貯器中的地址(由指令地址計數(shù)器給出),把指令從存貯器中取出來之后,需要有一個專門用于存放指令的地方,以便對指令進行分析和執(zhí)行。 這個專門存放現(xiàn)行指令的部件就叫做指令寄存器 。

后面會具體匯編代碼會涉及到。

關于寄存器就講這么幾個吧,hack過程夠用了。

2.內(nèi)存

這里講解的內(nèi)存一般是指高速緩存(Cache)或者主存。

計算機在運行程序時,首先將程序從磁盤讀取到主存,然后CPU按規(guī)則從主存中取出指令,數(shù)據(jù)并執(zhí)行指令,但是直接從主存(一般是DRAM)中讀寫是很慢的,所以引入了高速緩存(Cache)(使用的是SRAM)。

圖片

在程序運行前首先會試圖將指令,數(shù)據(jù)從主存中讀取到Cache中,然后在程序執(zhí)行時直接訪問Cache, 如果指令和數(shù)據(jù)可以從Cache中讀取到,那么就說是“命中(hit)”,反之就是“不命中(miss)”, miss情況下需要從主存中讀取指令或者數(shù)據(jù),這樣會直接影響CPU的性能,所以命中率對CPU來說至關重要。

內(nèi)存在計算中又會分為:堆區(qū),棧區(qū),全局(靜態(tài))區(qū),常量區(qū),代碼區(qū)等等。

圖片

這里講解下hack中比較關鍵的棧區(qū)。

棧區(qū)

  • 棧中存放了局部變量,參數(shù),函數(shù)的返回地址等
  • 棧區(qū)由編譯器自動分配釋放,由操作系統(tǒng)自動管理,無須手動管理
  • 棧區(qū)中的局部變量只在該函數(shù)作用域中有效,函數(shù)退出后就會被銷毀、

    棧區(qū)就像一個桶一樣,桶底就是棧底為高地址區(qū),桶的頂部為低地址, 桶中放東西當然是先放桶底然后依次疊加咯,也就是平時所說的FILO先進后出的模式。

圖片

3.CPU

1.CPU的功能

指令控制(程序的順序控制)
操作控制(一條指令由若干操作信號實現(xiàn))
時間控制(指令各個操作實施時間的定時)
數(shù)據(jù)加工(算術運算和邏輯運算)

2.CPU的基本組成

中央處理器 CPU= 運算器 + 控制器
運算器:
ALU
累加器
暫存器
控制器
程序計數(shù)器 (PC) 、指令寄存器 (IR) 、數(shù)據(jù)緩沖器 (DR) 、地址寄存器 (AR) 、通用寄存器、狀態(tài)寄存器 (PSW) 、時序發(fā)生器、指令譯碼器 (ID) 、總線

圖片

CPU的工作分為以下 5 個階段:取指令階段、指令譯碼階段、執(zhí)行指令階段、訪存取數(shù)和結果寫回。

  • 取指令 (IF,instruction fetch),即將一條指令從主存儲器中取到指令寄存器的過程。程序計數(shù)器中的數(shù)值,用來指示當前指令在主存中的位置。當 一條指令被取出后,程序計數(shù)器(PC)中的數(shù)值將根據(jù)指令字長度自動遞增。
  • 指令譯碼階段 (ID,instruction decode),取出指令后,指令譯碼器按照預定的指令格式,對取回的指令進行拆分和解釋,識別區(qū)分出不同的指令類 別以及各種獲取操作數(shù)的方法?,F(xiàn)代CISC處理器會將拆分已提高并行率和效率
  • 執(zhí)行指令階段 (EX,execute),具體實現(xiàn)指令的功能。CPU的不同部分被連接起來,以執(zhí)行所需的操作。
  • 訪存取數(shù)階段 (MEM,memory),根據(jù)指令需要訪問主存、讀取操作數(shù),CPU得到操作數(shù)在主存中的地址,并從主存中讀取該操作數(shù)用于運算。部分指令不需要訪問主存,則可以跳過該階段。
  • 結果寫回階段 (WB,write back),作為最后一個階段,結果寫回階段把執(zhí)行指令階段的運行結果數(shù)據(jù)“寫回”到某種存儲形式。結果數(shù)據(jù)一般會被寫到CPU的內(nèi)部寄存器中,以便被后續(xù)的指令快速地存??;許多指令還會改變程序狀態(tài)字寄存器中標志位的狀態(tài),這些標志位標識著不同的操作結果,可被用來影響程序的動作。 在指令執(zhí)行完畢、結果數(shù)據(jù)寫回之后,若無意外事件(如結果溢出等)發(fā)生,計算機就從程序計數(shù)器中取得下一條指令地址,開始新一輪的循環(huán),下一個指令周期將順序取出下一條指令。 [1] 許多復雜的CPU可以一次提取多個指令、解碼,并且同時執(zhí)行。

一些基礎的匯編命令:

1.數(shù)據(jù)傳送指令

  • 1.mov :傳送指令,也可以單純理解為賦值語句,這個語句在匯編中是最常用的。 格式:mov det,src

    首先mov語句分以下幾種情況:

    • 1.CPU內(nèi)部寄存器之間數(shù)據(jù)傳送:mov ebp,esp ,將esp寄存器中的數(shù)據(jù)傳遞給ebp寄存器。
    • 2.立即數(shù)傳遞到通用寄存器:mov ebp 3 ,將立即數(shù)3傳遞到ebp寄存器中。
    • 3.立即數(shù)傳遞到內(nèi)存存儲單元:mov [bx] 123h,將立即數(shù)傳遞到bx指向的內(nèi)存地址中。
    • 4.內(nèi)存和CPU之間數(shù)據(jù)傳送:內(nèi)存?zhèn)鬟f到CPU寄存器中:mov eax,dword ptr [a] ,CPU寄存器傳遞到內(nèi)存中:mov dword ptr [a],eax。

2.加減運算指令

首先要了解,加減法運算是會改變狀態(tài)寄存器中的值的,如一個有符號數(shù)的運算高位溢出標志(OF),無符號的運算進位標志(CF)等。

加法指令:add、adc、inc

  • 1.add
    格式:add OPRD1,OPRD2
    功能:OPRD1 = OPRD1 + OPRD2
    舉例:
    add eax ecx;//得到的結果為eax = eax+ecx;
    
  • 2.adc
    格式:add OPRD1,OPRD2
    功能:OPRD1 = OPRD1 + OPRD2
    舉例:
    adc eax ecx;得到的結果為eax = eax+ecx+狀態(tài)寄存器中給的進位標志CF;
    
  • 3.inc
    格式:add OPRD
    功能:OPRD = OPRD + 1
    舉例:
    inc eax;//得到的結果為eax = eax+1;
    

減法指令:sub,dec,cmp,當然還有和adc對應的sbb 這里講解下sub和dec

  • 1.sub
    格式:sub OPRD1,OPRD2
    功能:OPRD1 = OPRD1 - OPRD2
    舉例:
    sub eax ecx;//得到的結果為eax = eax - ecx;
    
  • 2.dec
    格式:dec OPRD
    功能:OPRD = OPRD - 1
    舉例:
    dec eax;//得到的結果為eax = eax - 1;
    
  • 3.cmp
    格式:cmp OPRD1,OPRD2
    功能:執(zhí)行OPRD1 - OPRD2,但運算結果不運送到OPRD1
    注:該指令通過OPRD - OPRD2影響標志位CF、ZF、SF、OF、AF、PF來判斷OPRD1和OPRD2的大小關系。
    通過ZF判斷是否相等;如果是無符號數(shù),通過CF可判斷大小;如果是有符號數(shù),通過SF和OF判斷大小
    

3.邏輯運算和移位指令

1、邏輯運算指令:not、and、or、xor、test

  • (1) NOT:非運算
    格式:NOT OPRD
    功能:把操作數(shù)OPRD取反,然后送回OPRD。
    注:    OPRD可以是通用寄存器,也可以是存儲器操作數(shù),此指令對標志沒有影響
    
  • (2) AND:與運算
    格式:AND OPRD1,OPRD2
    功能:對兩個操作數(shù)進行按位邏輯“與”運算,結果送到OPRD1中
    注: 該指令執(zhí)行后,CF=0,OF=0,標志PF、ZF、SF反映運算結果,AF未定義。
    某個操作數(shù)與自身相與,值不變,但可以使CF置0。
    
  • (3) OR:或運算
    格式:OR OPRD1,OPRD2
    功能:對兩個操作數(shù)進行按位邏輯“或”運算,結果送到OPRD1中
    注: 該指令執(zhí)行后,CF=0,OF=0,標志PF、ZF、SF反映運算結果,AF未定義。
    某個操作數(shù)與自身相或,值不變,但可以使CF置0。
    
  • (4) XOR:異或運算
    格式:XOR OPRD1,OPRD2
        功能:對兩個操作數(shù)進行按位邏輯“異或”運算,結果送到OPRD1中
    

2、一般移位指令:SAL/SHL,SAR/SHR

  • (1) SAL/SHL(Shift Arithmetic Left / Shift Logic Left);算術左移/邏輯左移
    格式:SAL OPRD,m
    SHL OPRD,m
    功能:把操作數(shù)OPRD左移m位,每移動一位,右邊用0補足1位,移出的最高位進入標志位CF
    注:    算術左移和邏輯左移進行相同的動作,為了方便提供了兩個助記符。
    
  • (2) SAR(Shift Arithmetic Right) ;算數(shù)右移指令
    格式:SAR OPRD,m
    功能:操作數(shù)右移m位,同時每移1位,左邊的符號位保持不變,移出的最低位進入標志位CF
    注:  對有符號數(shù)和無符號數(shù),算數(shù)右移1位相當于除以2
    如:SAR BH,1 ;(BH)= 80H,指令執(zhí)行后(BH)= C0H
    
  • (3) SHR(Shift Logic Right) ;邏輯右移指令
    格式:SHR OPRD,m
    功能:操作數(shù)右移m位,同時每移1位,左邊用0補足,移出的最低位進入標志位CF
    注:    對無符號數(shù),邏輯右移1位相當于除以2
    如:SHR AH,1 ;(AH)= 80H,指令執(zhí)行后(AH)= 40H
    

切記:算術移位和邏輯移位的區(qū)別:

對于左移不管是算術移位和邏輯移位,低位都補0; 對于右移的算術移位:對于有符號數(shù),符號位不變,然后整體右移。

4.轉(zhuǎn)移指令

1、無條件轉(zhuǎn)移指令:JMP(Jump)

直接跳轉(zhuǎn)到Jump指定的地址, 跳轉(zhuǎn)指令也是改變當前eip的值來決定的 ,這樣下次取指令會去新的eip地址下取。

格式:JMP OPRD
功能:使控制指令無條件轉(zhuǎn)移到OPRD的內(nèi)容給定的目標地址處。操作數(shù)OPRD可以是通用寄存器,也可以是字存儲單元
例如:
jmp cx                    ;CX寄存器的內(nèi)容送IP
jmp word ptr [1234h]    ;字存儲單元[1234h]的內(nèi)容送IP
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    22

    文章

    2108

    瀏覽量

    73651
  • 匯編代碼
    +關注

    關注

    0

    文章

    23

    瀏覽量

    7551
  • hacker
    +關注

    關注

    0

    文章

    4

    瀏覽量

    1365
收藏 人收藏

    評論

    相關推薦

    C++STL算法(二)

    C++STL算法(二)
    的頭像 發(fā)表于 07-18 14:49 ?1052次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>之</b>STL算法(二)

    c++STL算法(三)

    c++STL算法(三)
    的頭像 發(fā)表于 07-18 15:00 ?1294次閱讀
    <b class='flag-5'>c++</b><b class='flag-5'>之</b>STL算法(三)

    C++文件操作

    C++文件操作
    的頭像 發(fā)表于 07-21 10:52 ?1116次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>之</b>文件操作

    C++教程之函數(shù)的遞歸調(diào)用

    C++教程之函數(shù)的遞歸調(diào)用 在執(zhí)行函數(shù) f 的過程中,又要調(diào)用 f 函數(shù)本身,稱為函數(shù)的遞歸調(diào)用;形式
    發(fā)表于 05-15 18:00 ?35次下載

    C++課程資料詳細資料合集包括了:面向?qū)ο蟪绦蛟O計與C++,算法,函數(shù)

    本文檔的主要內(nèi)容詳細介紹的是C++課程資料資料合集包括了:面向?qū)ο蟪绦蛟O計與C++,算法,函數(shù),概述, C++語言基礎,構造數(shù)據(jù)類型,數(shù)據(jù)類型,C+
    發(fā)表于 07-09 08:00 ?18次下載
    <b class='flag-5'>C++</b>課程資料詳細資料合集包括了:面向?qū)ο蟪绦蛟O計與<b class='flag-5'>C++</b>,算法,<b class='flag-5'>函數(shù)</b>等

    如何在中斷C函數(shù)中調(diào)用C++

    之前,我們在單片機程序開發(fā)時都會面對中斷函數(shù)。眾所周知的,這個中斷函數(shù)肯定是要用C函數(shù)來定義的。我在用C++進行程序開發(fā)的時候就發(fā)現(xiàn)了一個需
    發(fā)表于 05-09 18:17 ?0次下載
    如何在中斷<b class='flag-5'>C</b><b class='flag-5'>函數(shù)</b>中調(diào)用<b class='flag-5'>C++</b>

    C++重載函數(shù)學習總結

    函數(shù)重載是c++c的一個重要升級;函數(shù)重載通過參數(shù)列表區(qū)分不同的同名函數(shù);extern關鍵字能夠?qū)崿F(xiàn)c
    的頭像 發(fā)表于 12-24 17:10 ?798次閱讀

    EE-128:C++中的DSP:從C++調(diào)用匯編類成員函數(shù)

    EE-128:C++中的DSP:從C++調(diào)用匯編類成員函數(shù)
    發(fā)表于 04-16 17:04 ?2次下載
    EE-128:<b class='flag-5'>C++</b>中的DSP:從<b class='flag-5'>C++</b>調(diào)用匯編類成員<b class='flag-5'>函數(shù)</b>

    C++基礎語法inline 內(nèi)聯(lián)函數(shù)

    上節(jié)我們分析了C++基礎語法的const,static以及 this 指針,那么這節(jié)內(nèi)容我們來看一下 inline 內(nèi)聯(lián)函數(shù)吧! inline 內(nèi)聯(lián)函數(shù) 特征 相當于把內(nèi)聯(lián)函數(shù)里面的內(nèi)
    的頭像 發(fā)表于 09-09 09:38 ?2150次閱讀

    C++ C語言函數(shù)查詢電子版下載

    C++ C語言函數(shù)查詢電子版下載
    發(fā)表于 01-18 10:15 ?0次下載

    深度解析C++中的虛函數(shù)

    函數(shù)作為C++的重要特性,讓人又愛又怕,愛它功能強大,但又怕駕馭不好,讓它反咬一口,今天我們用CPU的角度,撕掉語法的偽裝,重新認識一下虛函數(shù)。 虛函數(shù)
    的頭像 發(fā)表于 02-15 11:14 ?838次閱讀
    深度解析<b class='flag-5'>C++</b>中的虛<b class='flag-5'>函數(shù)</b>

    C++學習筆記c++的基本認識

    自這篇文章我們即將開始C++的奇幻之旅,其內(nèi)容主要是讀C++ Primer的總結和筆記,有興趣可以找原版書看看,對于學習C++還是有很大幫助的。這篇文章將從一個經(jīng)典的程序開始介紹C++
    的頭像 發(fā)表于 03-17 13:57 ?739次閱讀

    C/C++函數(shù)hack(下)

    首先來說下 什么是hack ? hack字面意思“ 非法入侵 ”,那么在C/C++中其實就是 使用反匯編查看C/
    的頭像 發(fā)表于 03-30 16:53 ?1223次閱讀
    <b class='flag-5'>C</b>/<b class='flag-5'>C++</b><b class='flag-5'>之</b><b class='flag-5'>函數(shù)</b><b class='flag-5'>體</b><b class='flag-5'>hack</b>(下)

    C++基礎知識函數(shù)1

    函數(shù)C++ 中的一個重要概念,它可以讓我們將一段代碼封裝起來,然后在需要的時候調(diào)用它。C++ 中的函數(shù)有以下幾個特點: * 函數(shù)
    的頭像 發(fā)表于 04-03 10:34 ?579次閱讀

    同樣是函數(shù),在CC++中有什么區(qū)別

    同樣是函數(shù),在 CC++ 中有什么區(qū)別? 第一個返回值。 C語言的函數(shù)可以不寫返回值類型,編譯器會默認為返回 int。 但是
    的頭像 發(fā)表于 11-29 10:25 ?308次閱讀