1. 程式人生 > >往程式碼區空白區加一段程式碼

往程式碼區空白區加一段程式碼

知識點1

先舉一個例子:
這裡寫圖片描述
上圖中E9 63210000為硬編碼(也叫OpCode),63210000是以小端進行顯示的,它實際的結果為0000 21 63,本文中表示地址偏移的硬編碼統統設為X

知識點2

下面介紹一個公式:

真正要跳轉的地址 =  E8這條指令的下一行地址 + X;這裡的X指的就是硬編碼;

X = 真正要跳轉的地址(其實就是目標地址) - E8這條指令的下一行地址
舉例來說明驗證:

地址                 硬編碼                        彙編
004011F8       E8  53 FE FF FF           call  function
(0040 1050)
004011FD 33 C0 xor eax , eax

這裡驗證一下這個公式:
這個例子中E8 (call)這條指令的下一行的指令地址為004011FD ,要跳往的地址為 0040 1050(這兩者皆為16進位制)
X = 0040 1050 - 004011FD = FFFF FE53 (請用計算器計算)
這裡的FFFF FE53用小端寫出來就是FFFF FE53 !

再看一個jmp(E9)的例子:
00401050  E9  2B 2B 00 00   jmp  Function(00403B80)   //這是第一條指令 
00401055  CC  int 3   //這是下一條指令
X = 00403B80 - 00401055 = 00 00 2B 2B 得到硬編碼為 2B 2B 00 00
公式變換

其實E8/E9後面跟了4個位元組,故整個長度為5個位元組;故:
E8這條指令的下一行地址=E8這條指令的地址+5
所以上面公式變為:

X = 要跳轉的地址 - ( E8(E9)這條指令所在地址 + 5) //這裡的地址為”拉伸”後的在記憶體中執行的地址!!!

添往程式中新增加程式碼例子

下面一個例子就是要在一個程式裡面新增一段有關Messagebox的程式碼,

知識點0x00

Push 0的硬編碼如下:
6A 00 push 0
6A 00 push 0
6A 00 push 0
6A 00 push 0

往程式碼段新增一段如下的程式碼:
6A 00 6A 00 6A 00 6A 00 E8 00 00 00 00 E9 00 00 00 00

知識點0x01

首先要看程式碼段剩下的空間能不能夠容納下這18個位元組???(E8 與call 對應,E9 與jmp對應)
用SizeofRawData - VirtualSize即可!這裡檢測到是可以的

知識點0x02

MessageBox的地址為77 E5 42 5F
call message 的下一條指令地址:41A73D(這個地址其實就是E9 所對應的那個地址)
所以X = 77 E5 42 5F-41A73D= 77A3 9B22 對應硬編碼為22 9B A3 77
所以E8 00 00 00 00填充為E8 22 9B A3 77

知識點0x03

OEP為00 01 83 D7(這是可選頭裡面的,是一個RVA)
Imagebase為0x40 0000
故入口點位置為00 41 83 D7(目標地址)
而 E9 00 00 00 00這條指令的下一條指令的地址可以通過PE工具找出來,就是你在ImageBuffer裡面的那個區段添加了這18個位元組的指令之後的那個地址,這裡為1A742,再加上40 0000,為41 A7 42,
故這裡的X = 00 41 83 D7(目標地址)-41 A742=FFFF DC95 對應硬編碼為95 DC FF FF
所以這裡E9 00 00 00 00填充為E9 95 DC FF FF

知識點0x04更改OEP

最後要思考的是新增這段程式碼,我們要實現的效果是 先彈出一個MessageBox的對話方塊,然後再執行原來的exe程式,
而我們要新增的6A 00 6A 00 6A 00 6A 00 E8 22 9B A3 77 E9 95 DC FF FF這段程式碼的起始地址是1A730(這裡沒有加ImageBase),要想實現上面所說的效果,就必須把原來的OEP(1 83 D7)改為1A730即可

總結:

實現邏輯:將原來的OEP改為新增的程式碼的因編碼所在地址,這樣程式執行的時候就從你新增的程式碼開始執行了,而新增的程式碼的硬編碼為E9 95 DC FF FF,這句話的邏輯是跳往原來exe的OEP,硬編碼計算公式見上

注意:注入的概念是這個程式碼本身已經在運行了,我把我的程式碼”扔”進去,而這裡在程式碼為執行之前將程式碼加進去