內核變數引用
1. 如何調用linux內核源碼中的全局變數
不會首先全局變數是不佔堆棧空間的全局全量編譯的時侯是放在.data段的只有沒有static修飾的局部變數在程序運行的時侯臨時分配在棧上,new,或malloc等定義的變數分配在堆上如果想讓棧溢出也很容易,棧也有其極限的,只要定義一個無限遞歸函數,讓它沒完沒了的遞歸就行了,一會就崩了。建議學一下編譯原理
2. 元格中的一個引用地址的一部分需要作為變數被賦值
offset函數,可以改變區域位置、大小。應該是最合適這個場景的函數了。
另外用indirect+address也能實現,比較別扭一些。
3. 如何獲取windows內核全局變數的辦法
1、ImageBase = LoadLibraryA("ntoskrnl.exe")
2、GetProcAddress(ImageBase,"MmGetSystemRoutineAddress")
3、搜索特徵代碼:
*(WORD *)(MmGetSystemRoutineAddress + i) = 0x358b && *(WORD *)(MmGetSystemRoutineAddress + i + 6) = 0xfe81
&&
*(DWORD *)(MmGetSystemRoutineAddress + i + 2) == *(DWORD *)(MmGetSystemRoutineAddress + i + 8)
4、定位內核中的地址:
PsLoadedMoleList = *(DWORD *)(MmGetSystemRoutineAddress + i + 2) + (KernelBase - ImageBase)
4. 安卓hardwa層可以引用內核中的變數嗎
對於對象類型的數據,引用就相當如對象指針,保存的那個對象的地址,使用的時候根據地址找對象。 對於普通類型的數據,這個引用就是直接存放那個數據了。使用就不用像對象那樣去找了。 對象引用是中介,普通數據引用真正的客戶。 int a = 1;int b;b=a此時是直接把a的值也就是地址賦給b(而不是「1」)。。 b =a ,是傳值不是地址,對象是傳地址。怎麼證明這點很簡單,你改變a的值,如果b變了就是傳地址,否則就是值了。
5. 為什麼內核中的程序變數或函數 都用static修飾呢
static 修飾函數 表示函數只能在本文件中使用
static 修飾全局變數 表示該全局變數只能在本文件中使用
static 修飾局部變數 表示該變數只在第一次用到的時候被初始化,以後用到該變數時都是用的上次的值
6. 如何獲取Windows 系統的內核變數
PsLoadedMoleList等重要內核變數並未被ntoskrnl.exe導出,也沒有公開的函
數可以獲取。而這些內核變數對於Rootkit、Anti-Rootkit 以及內核溢出的利用等都
是至關重要的。
下面我們以PsLoadedMoleList、PsActiveProcessHead 等為例,介紹得到這些
變數的方法。
對於Windows NT 4.0和Windows 2000,尚沒有「溫柔」的辦法可以獲取這些變數,
比較理想的辦法也就是特徵代碼搜索,這種方法雖然暴力,但通常都很有效,一般也
不會出問題;對於Windows XP和Windows 2003,我們找到了一些更加優雅的選擇。
下面首先介紹特徵代碼搜索的方法。
[DWORD KernelBase]
要進行特徵代碼搜索,首先要定位ntoskrnl.exe在內核的載入地址KernelBase。
這個地址可以通過ZwQuerySystemInformation Class 10的SystemMoleInformation
來得到。參考資源[1]中給出了相關代碼。事實上,KernelBase 這個值對同一操作系
統來說非常固定,可以作為常量來用:
Windows NT: 0x80100000
Windows 2000:0x80400000
Windows XP: 0x804d1000
Windows 2003: 0x804e0000
Windows NT 4.0 ntoskrnl.exe 的OptionalHeader->ImageBase = 0x80100000,
ntldr 也會按照這個值來載入內核,但是從Windows 2000開始就不是這樣了。可能基
於這個歷史原因,各系統的*(DWORD *)PsNtosImageBase始終初始化為0x80100000。
另外,內核變數PsNtosImageBase、KdpNtosImageBase等也指向KernelBase:
KernelBase = *(DWORD *)PsNtosImageBase
KernelBase = *(DWORD *)KdpNtosImageBase
[LIST_ENTRY PsLoadedMoleList]
PsLoadedMoleList這個全局變數指向一個保存著所載入驅動信息的雙向鏈表。
通過它可以枚舉系統中所有的驅動模塊。
雖然很多內核函數都用到了PsLoadedMoleList,但是大部分並沒有被導出,而
從基址開始搜會很花時間。對於Windows 2000來說,從下面這個地方入手是個好主意:
nt!MmGetSystemRoutineAddress+0x66:
804f0ed0 8b35f0e84680 mov esi,[nt!PsLoadedMoleList (8046e8f0)]
804f0ed6 81fef0e84680 cmp esi,0x8046e8f0
流程如下:
1、ImageBase = LoadLibraryA("ntoskrnl.exe")
2、GetProcAddress(ImageBase,"MmGetSystemRoutineAddress")
3、搜索特徵代碼:
*(WORD *)(MmGetSystemRoutineAddress + i) = 0x358b && \
*(WORD *)(MmGetSystemRoutineAddress + i + 6) = 0xfe81
&&
*(DWORD *)(MmGetSystemRoutineAddress + i + 2) == \
*(DWORD *)(MmGetSystemRoutineAddress + i + 8)
4、定位內核中的地址:
PsLoadedMoleList = \
*(DWORD *)(MmGetSystemRoutineAddress + i + 2) + (KernelBase - ImageBase)
從SP0到SP4,i值並不相同,但是肯定不大於0x100。
對Windows NT來說,就沒這么好運氣了,沒有理想的可用於定位的API,只能從頭
開始搜索。下面這段代碼至少對SP1~SP6a的來說都具有很好的穩定性和唯一性:
801CEB1C: 8B 4D 08 mov ecx,dword ptr [ebp+8]
801CEB1F: 89 01 mov dword ptr [ecx],eax
801CEB21: 8B 45 0C mov eax,dword ptr [ebp+0Ch]
801CEB24: 89 10 mov dword ptr [eax],edx
801CEB26: 8B 36 mov esi,dword ptr [esi]
801CEB28: 81 FE 70 0B 15 80 cmp esi,80150B70h //PsLoadedMoleList
如果是用驅動做這件事情,就不必暴力搜索了,fuzen_op(fuzen_op@yahoo.com)
在FU_Rootkit2.0(參考資源[2])中使用了一段比較巧妙的代碼:
DWORD FindPsLoadedMoleList (IN PDRIVER_OBJECT DriverObject)
{
PMODULE_ENTRY pm_current;
if (DriverObject == NULL)
return 0;
pm_current = *((PMODULE_ENTRY*)((DWORD)DriverObject + 0x14));
if (pm_current == NULL)
return 0;
gul_PsLoadedMoleList = pm_current;
while ((PMODULE_ENTRY)pm_current->le_mod.Flink != gul_PsLoadedMoleList)
{
if ((pm_current->unk1 == 0x00000000) && \
(pm_current->driver_Path.Length == 0))
{
return (DWORD) pm_current;
}
pm_current = (MODULE_ENTRY*)pm_current->le_mod.Flink;
}
return 0;
}
[LIST_ENTRY PsActiveProcessHead]
理論上PsActiveProcessHead 也可以用搜索代碼的方法來取,但是還有更簡單的
方法。
ntoskrnl.exe導出的PsInitialSystemProcess 是一個PEPROCESS,指向system進
程的EPROCESS。這個EPROCESS的結構成員EPROCESS.ActiveProcessLinks.Blink 就是
PsActiveProcessHead:
kd> dt _EPROCESS ActiveProcessLinks.Blink poi(PsInitialSystemProcess)
+0x0a0 ActiveProcessLinks : [ 0x81356900 - 0x8046e728 ]
+0x004 Blink : 0x8046e728 [ 0x81a2fb00 - 0xff5a4ce0 ]
kd> ? PsActiveProcessHead
Evaluate expression: -2142836952 = 8046e728
EPROCESS這個結構在不同的操作系統上各不相同,需要分別對待。
[struct _KDDEBUGGER_DATA64 KdDebuggerDataBlock]
Windows 2000 開始,系統引入了變數KdDebuggerDataBlock。其中包含了大量的
內核變數。如果能夠獲取到的話,可以解決許多問題。遺憾的是,Windows NT上沒有
這個變數。WinDBG SDK的wdbgexts.h中包含了它的結構:
typedef struct _KDDEBUGGER_DATA64
因為比較長,這里就不引用了。
從對5.0.2195.6902版本ntoskrnl.exe 的逆向工程結果來看,只有兩個函數使用
了該變數,並且,兩個函數都未導出,且代碼前後沒有明顯特徵,無法靠直接搜索代
碼來獲取。
但是,我們發現,ntoskrnl.exe導出了KdEnableDebugger,KdEnableDebugger會
調用KdInitSystem,而KdInitSystem 中引用了KdDebuggerDataBlock:
n < 100
Windows 2000:
KdEnableDebugger + n:
6A 00 push 0
6A 00 push 0
C6 05 28 41 48 00 01 mov _PoHiberInProgress, 1
E8 1C DC 10 00 call _KdInitSystem@8 ; KdInitSystem(x,x)
KdInitSystem + n:
68 70 02 00 00 push 270h // sizeof(KdDebuggerDataBlock)
B9 50 D1 54 00 mov ecx, offset _KdpDebuggerDataListHead
68 D8 FA 46 00 push offset KdDebuggerDataBlock
8B 40 18 mov eax, [eax+18h]
68 4B 44 42 47 push 4742444Bh // "KDBG",可以用作搜索的定位標志
A3 3C D1 54 00 mov ds:_KdpNtosImageBase, eax
89 0D 54 D1 54 00 mov ds:dword_54D154, ecx
89 0D 50 D1 54 00 mov ds:_KdpDebuggerDataListHead, ecx
Windows XP
KdEnableDebugger + n:
6A 00 push 0
6A 00 push 0
C6 05 8C 98 47 00 01 mov _PoHiberInProgress, 1
E8 2B 17 13 00 call _KdInitSystem@8 ; KdInitSystem(x,x)
KdInitSystem + n:
68 90 02 00 00 push 290h
68 E0 9D 46 00 push offset KdDebuggerDataBlock
BE 74 96 59 00 mov esi, offset _KdpDebuggerDataListHead
68 4B 44 42 47 push 4742444Bh
89 35 78 96 59 00 mov ds:dword_599678, esi
89 35 74 96 59 00 mov ds:_KdpDebuggerDataListHead, esi
Windows 2003
KdEnableDebugger + n:
56 push esi
56 push esi
C6 05 0C 08 49 00 01 mov PoHiberInProgres, 1
E8 CB AD 15 00 call _KdInitSystem@8 ; KdInitSystem(x,x)
KdInitSystem + n:
68 18 03 00 00 push 318h
68 D0 A3 47 00 push offset KdDebuggerDataBlock
BE 18 10 5D 00 mov esi, offset _KdpDebuggerDataListHead
68 4B 44 42 47 push 4742444Bh
89 35 1C 10 5D 00 mov ds:dword_5D101C, esi
89 35 18 10 5D 00 mov ds:_KdpDebuggerDataListHead, esi
可以看出,上面代碼特徵的唯一性很好。用於搜索是沒有問題的。我在上面同時
列出了三個系統的代碼,僅僅只是為了比較,事實上,對Windows XP和Windows 2003
是完全沒有必要採取如此暴力手段的。
7. php中的可變變數和引用賦值有什麼區別
從PHP內核的角度跟你解釋下吧,你可以深入理解下,就完全明白了;
PHP的變數在內核中都是通過C語言的結構zval來存儲的(你沒學過C,你可以理解為是個對象,裡面的成員變數都是類的屬性,暫時先這樣理解),zval結構如下:
struct _zval_struct {
zvalue_value value; // 存儲變數的值
zend_uint refcount__gc; //表示引用計數 默認為:1
zend_uchar type; // 變數具體的類型
zend_uchar is_ref__gc; //表示是否為引用
};
舉個例子,php代碼如下:
$a = 10;
$b = $a;
這時$b沒有引用,只是將$a的值賦給了$a,那麼zval這個結構中的refcount__gc就變為2了,而is_ref__gc還是false,表示未引用,因為內核$a已經開辟了一塊內存空間,當$a賦值給$b時,$b的值只指向了$a,這樣就省去了重新開辟一塊內存,但是當$b值被改變時($a的值不會變),$b又將會開辟一塊新的內存空間,這就是所以的寫時復制,到這里,樓主已經明白了,PHP變數在內核中的如何存儲了,下面就講下引用:
$a = 10;
$b = &$a;
這個時候,內核中存儲$a的結構is_ref__gc標記為true,代表是引用,那麼$a和$b都指向了同一個內存地址,當$b=20的時候,$a也會變成20,說到這里,樓主應該明白區別了吧?