Anti Game hacking 프로그램의 구현.


Anti Game hacking 프로그램의 구현.



작성자 : Dual5651 (dual@null2root.org) in Null@Root

소개

 이번 글에서는 그 시점에서 알게된 Anti GH 프로그램이 갖추어야할 기능이 무엇
이며, 그 기능의 구현에 필요한 코드와 그 기능의 존재하는 약점등에 대해서 다루어
보고자 합니다. 이 글의 구성은 다음과 같습니다.

1. Anti Game Hacking 프로그램에 필요한 기능들.
2. Anti Game Hacking Program 구현에 필요한 코드들.


1. Anti Game Hacking 프로그램에 필요한 기능들.

 Anti GH 프로그램은 어떤 기능들이 필요할까요?

1. (Binary /Data File) Packing / Encrypting

2. GH Program Detecting

3. AutoPlay Blocking

4. Message Hooking Blocking

5. Unauthorized memory access Blocking

6. Debugging Blocking

7. SpeedHack Blocking

8. Integrity Checking

9. System descriptor restoring

 첫번째로 필요한 기능으로써, 실행파일 및 데이터 파일의 압축 또는 암호화
들 수 있습니다. 이 부분에 대해선 다른 의견을 가지고 있는 분들도 많은거 같습니다.
이런 분들의 주장에 근거로는 패킹 및 인크라입팅에 의존하면, 프로그램 자체의
Secure Coding이 약해지고, 대부분 이러한 패킹 및 인크라입팅은 범용적으로
사용되는 상용프로그램일 가능성이 높음으로, 풀릴(뚫릴 - 그만큼 공략하는 사람도
많기 때문에) 가능성도 높으며, 이로 인한 결과는 상상이상으로 치명적일 것이기
떄문입니다. 그럼에도 불구하고, 최근 실행파일의 패킹을 하지 않은 프로그램을
더 찾기 힘들만큼 많이 사용되어 지고 있으며, 또 어느정도 첫번째  방어선으로써
기대되어 지는 기능을 하여주고 있습니다.

그렇다면 게임의 데이터 파일들에 대한 패킹 및 인크라입팅은 왜 필요한 것일까요?
최근 Anti GH 프로그램의 도입으로 Memory Hacking이 힘들어지자, 최근 공격자들은
게임의 데이터파일을 조작하는 방식의(고전적이라면 고전적인 방법의) 해킹을 다시
시도하기 시작하였습니다. 실제 2007년도 국내의 어떤 게임에서는 해당 방식에 의한
GH이 이루어지기도 하였습니다.

 두번째로 필요한 기능으로써, 게임해킹 프로그램의 감지를 들 수 있습니다.
최근 가장 많이 쓰이는 GH방식으로 Memory Hacking이 있습니다.
이러한 MH(Memory Hacking)은 공격자 입장에서 Generic Game Hacking Tool
(ex: CheatEngine,Tsearch and so on...)로 우선 대상 Game에 대한 분석을 하고
그 후 그 게임만을 대상으로 하는 게임 트레이너가 나오게 됩니다.
즉, 범용 게임 해킹툴의 완전한 차단은 특정 게임 대상 트레이너의 제작을 막는 방법
이기도 합니다. 물런 이는 반드시 그러한 것은 아니며, 거의 근접한 %의 역활을 할 수
있습니다. 감지하는 방법으로써는 첫번째로 패턴 매칭이 있습니다.
패턴 매칭이란 특정한 GH 프로그램에서 발견되는 문자열이나, 코드배열등을
Anti GH프로그램에서 모든 프로세스에서 찾아 보고, 있다면 GH 프로그램으로
간주하는 방식입니다. 두번째로 Finding Named Object기법이 있습니다.
예를들어,
 hFileMap = CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE,NULL,
  PAGE_READWRITE,0,dwSize,"DUALMEM");

의 경우 처럼, GH 프로그램이 사용되는 시스템 전역에 공유되는 파일맵의 이름이라던지,
GH 프로그램의 창이름, 클레스 이름, 프로세스 이름, 로드되는 드라이버 이름, 뮤텍스,
레지스트리 키등등의 요소등을 검사해보는 방법입니다. 이러한 요소를 확인하는 방법은
sysinternals의 Process Explorer를 이용하여 해당 GH프로그램이 가지고 있는 핸들등
을 통해서 확인하여 볼 수 있습니다.


 세번째로 필요한 기능으로써, 자동 플레이 차단을 들 수 있습니다.
최근 메모리 해킹보다 더 큰 문제로 대두되고 있는 것이, 자동플레이 문제 입니다.
과거에는 '작업장'이라는 이름으로, 빈곤한 국가에서 아동 및 청소년의 노동력을
착취하여 지속적인 게임 플레이를 통한 아이템 획득하여, 이를 판매, 이익을 얻는
방식의 범죄가 존재한 반면, 최근에는 이러한 노동력 착취가 아닌, 자동으로
게임을 플레이 해주는 프로그램 및 하드웨어를 이용하여 자동적으로 플레이 하여,
아이템을 획득, 이를 판매하여, 이익을 얻는 방식으로 변모하였습니다.

최근 단순한 메크로 방식의 자동 플레이 보다 진화된 형태의 두가지 자동 플레이
방식이 등장하였는데,  첫번쨰로 게임 클라이언트와 서버와의 통신 프로토콜등을
분석하여 게임 클라이언트와 똑같은 기능을 하는 클라이언트를 만들어(UI는 없는)
해당 클라이언트에 AI를 붙이어 자동적으로 사냥하게 하는 것입니다.
이 방식으로 접근하게 될 경우, Anti GH프로그램은 올바른 역활을 할 수 없게 되며,
서버측의 입장에서도 올바른 클라이언트와 공격자에 의해 만들어진 오토 플레이용
클라이언트를 분간하는 것도 현재로선, 명확한 방법은 존재하지 않습니다.
또 이 방식의 공격은 2차적인 피해를 낮기도 하는데, 이런 오토 플레이로써 기능을
하다가, 후에는 '프리 서버'라는 이름으로 판매되어, 실제 게임의 플레이어 수를
줄이고, 저작권을 침해하는 범죄가 2차적으로 이어집니다.
두번쨰로 하드웨어 방식의 오토 플레이 입니다. 이는 실제 사용자에 의해 이뤄지는
올바른 입력과 분간하는 것이 힘듭니다. 이를 분간하기 위한 방법으로써, 행동
패턴 기반의 감지방법이나, WMI등을 이용, 하드웨어의 ID를 확인하여 오토 플레이용
하드웨어를 감지하는 방법등이 사용되어 지고 있습니다.

 네번쨰로 필요한 기능으로써, 메시지 후킹 차단을 들 수 있습니다.
공격자는 메시지 후킹을 사용자의 키입력등을 가로 챌 목적으로 사용합니다.
게임의 경우, 키 입력을 가로채어, 아이디와 패스워드등을 알아낸 후,
접속하여 아이템등을 빼가는 등의 범죄에 사용되어 집니다.
현재 존재하는 대부분의 Anti GH 프로그램등은 대부분 기본적으로 유저레벨단의
메시지 후킹을 차단하고 있으며, 이로 인해 최근에는 키로거들도 유저레벨에서
메시지 후킹을 하는 방식이 아닌, 커널레벨에서 필터 드라이버등으로써 키로거
기능을 수행하고 있습니다.

 다섯번쨰로 필요한 기능으로써, 허용되지 않은 메모리 접근차단을 들 수 있습니다.
매시각각 생겨나는 GH 프로그램에 대응한다는 것은 참 힘든일이며,
Private한 GH 프로그램에 대해선 대응하기가 힘들다는 이유에서 이 방법은 Anti GH에
큰 도움이 되는 방법입니다. 게임 및 보호 프로그램의 프로세스에 허용되지 않은
접근을 차단함으로써, Private한 GH 프로그램도 견제할 수 있게 됩니다.
이를 수행하기 위해서 유저레벨에서는 각 프로세스에 Dll을 삽입하여, API를 후킹하게
하고, 커널레벨에서는 NtOpenProcess(), NtRead/WriteVirtualMemory()등의 함수를
후킹하여 프로세스로의 접근을 차단합니다. 그러나 최근 GH 프로그램도 이런 후킹에
대응하기 위하여, 기존의 API를 호출하는 것이 아닌, Pesudo 코드를 사용함으로써,
위에서 말했던 API들로는 충분치 않아, 최근에는 KeAttachProcess() 같은 프로세스
메모리 전환 계열 함수도 후킹대상에 포함되고 있습니다.

 여섯번쨰로 필요한 기능으로써, 디버깅 차단을 들 수 있습니다.
게임을 디버거에게 내준다는 것은, 알몸을 보여주는 것과 같습니다.
그럼으로, 디버거는 어떻게든 차단해야 하는 존재입니다. 디버거를 감지하는
방법으로는 우선 앞에서 말했던 요소들을 혼합함으로써 이루어 질 수 있습니다.
디버거들이 사용하는 API(DebugActiveProcess)같은 프로세스들을 후킹하는
것도 중요하며, 유명한 범용 디버거가 있는지 정기적으로 확인하여, 이들의
창이름, 클레스 이름, 프로세스 이름등 Anti GH프로그램의 두번쨰 기능에서
거론한 요소들로 감지할 수 있으며, 디버거 역시 유저레벨 디버거의 경우
다섯번째 기능으로 차단되며, 커널레벨 디버거의 경우는 반드시 두번쨰 기능을
이용하여 차단되어져야 합니다. 유명한 커널레벨 디버거로써는 SoftIce와
syser가 있으며, 필수적인 차단리스트 입니다.

 일곱번째로 필요한 기능으로써, 스피드 핵 차단을 들 수 있습니다.
공격자 입장에서 생각하기에는 단순히 스피드 핵을 차단하는 이유가 공정성 때문
이라고 생각할지 모르겠지만, 실제적으로 스피드 핵을 차단하는 이유는 공정성
그 이상의 이유가 있습니다. 스피드 핵을 사용할 경우 특정한 기능을 수행하는
루틴의 반복시간에 Gap이 짧아 짐으로써, (Delay시간의 감소) 서버로 유입되는
패킷량 역시 증가되게 됩니다. 만약, 스피드를 정상적인 속도에 10배로 하였다면,
서버로 보내는 패킷량도 10배에 근접하게 된다고 보시면 됩니다. 즉 반드시
차단해야 합니다. 스피드 핵은 두종류가 있는데, 첫번쨰는 GetTickCount() ,
timeGetTime(),QueryPerformanceCounter()등의 시간관련 함수를 후킹하는
방식이 있습니다. 이는 프로세스로의 메모리 접근을 차단함으로써 해결할 수
있는 문제입니다. (사실 메모리 접근을 하지 않고 후킹을 할 수도 있습니다.
-CopyOnWrite 관련) 두번쨰는 시스템의 PIT자체를 줄임으로써, 시스템 시간
전체를 빠르게 돌아가게 하는 방법이 있습니다. 이는 시스템 내부적으론 감지가
힘들게 되며, 서버와의 연동체크를 통해서 감지하는 방법이 있습니다.

 여덟번째로 필요한 기능으로써, 무결성 검사를 들 수 있습니다.
무결성 검사를 하는 이유로는, 만약 게임프로세스 및 보호 프로세스가 패킹이
해제되거나, 변조된 상태에서 실행된다면, Anti GH은 정상적인 기능을 수행할 수
없게 됩니다. 무결성 검사는 보호 프로세스가 시작될떄에, 게임 파일 및 보호
프로세스 자체 파일들에 대하여 우선적으로 이루어져야 하며,
실행 중에도 코드섹션에 대하여 정기적으로 이루어져야 합니다.
이렇게 검사를 수행할 경우, 만약 다섯번쨰 기능이 우회되여, 게임의 메모리나,
게임의 데이터 파일등이 수정되었다고 하여도, 이를 감지할 수 있습니다.

 아홉번째로 필요한 기능으로써, 시스템 디스크립터 복구를 들 수 있습니다.
게임이 시작하기전 시스템의 중요한 디스크립터들(ex: ssdt, idt, and so on)을
복구 하여둠으로써, 꺠끗한 환경에서 게임이 돌아가도록 해야 합니다.
이 작업이 수행되어 지지 않으면, Anti GH 프로그램은 올바른 작동을 할 수 없을
수도 있습니다.


2. Anti Game Hacking Program 구현에 필요한 코드들.

 앞에서는 안티 게임 해킹 프로그램이 갖추어야할 기능들에 대해서 알아 보았습니다.
이번에는 이러한 기능들을 구현하기 위해서 알아야 할 점 및 코드에 대해서 다루어
보도록 하겠습니다.

첫번째로 실행파일 및 데이터 파일의 압축 또는 암호화의 경우 코드의 길이가
짧은편이 아님으로, 관련 링크로 대신하도록 하겠습니다.
http://dual5651.hacktizen.com/tt/entry/Make-your-owner-PE-Protector-Part-1-Your-
first-EXE-Protector

참고 적으로 최근의 게임 EXE 패킹은 더미다 패커가 인기를 끌고 있고,
드라이버의 경우 Code Virtualizer가 인기를 끌고 있습니다.

두번쨰로 게임해킹 프로그램의 감지의 코드는 다음과 같습니다.

프로세스 메모리 영역의 패턴 검사 :

BOOL PatternSearchFromAllProcesses()
{
 char StringDataBase[][30] = {"CheatEngine",
          "AutoPlay",
          "GameHack",
          "Memory Search",
          "TSearch"};
 char szProcess[MAX_PATH] = {0,};
 DWORD ProcessesID[1024];
 char WarningString[MAX_PATH] = "게임 해킹 프로그램 발견 되었습니다.\n게임이 종료 됩니다.\n";
 MEMORY_BASIC_INFORMATION struct_mbi;
 SYSTEM_INFO struct_si;
 HMODULE hMod;
 DWORD dbNeeded,dbNeeded2;
 HANDLE hProcess;
 LPVOID newbuf;
 LPVOID p;
    ULONG ret;
 int cnt;
 GetSystemInfo(&struct_si); //Getting Information to get max,min address
 printf("StartAdr : 0x%x, EndAdr : 0x%x\n",
   struct_si.lpMinimumApplicationAddress,
   struct_si.lpMaximumApplicationAddress);
 for(cnt=0; ;cnt++)    //Counting Pattern
  if(!StringDataBase[cnt][0])
   break;
 
 EnumProcesses(ProcessesID,sizeof(ProcessesID),&dbNeeded); //Get Processes IDs.
 
 for(int i = 0; i < dbNeeded / sizeof(DWORD); i++)
 {
  if((ProcessesID[i] == GetCurrentProcessId()) || ProcessesID[i] == 4) continue; //Do not scan by self
 
  hProcess = OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,ProcessesID[i]);
 
  if(hProcess)
  {
   EnumProcessModules(hProcess,&hMod,sizeof(hMod),&dbNeeded2);
   GetModuleBaseName(hProcess,hMod,szProcess,sizeof(szProcess)); //Get Module Name
   p = struct_si.lpMinimumApplicationAddress;
   
   do
   {
      VirtualQueryEx(hProcess,p,&struct_mbi, sizeof(struct_mbi));
      newbuf = malloc(struct_mbi.RegionSize);
      //Sometimes regionSize makes me crazy!!!
      if(newbuf)
      {
       ReadProcessMemory(hProcess,p,newbuf,struct_mbi.RegionSize,&ret);
       if(ret)
       {
        for(DWORD i = (DWORD)newbuf; i <= (DWORD)newbuf+(DWORD)struct_mbi.RegionSize; i++)
        {
         for(int j = 0; j < cnt; j++)
         {
        if(!strnicmp((char *)StringDataBase[j],(char *)i,strlen((char *)StringDataBase[j])))
        {
         strcat(WarningString,szProcess);
         strcat(WarningString,"프로세스를 종료하신후 다시 실행하여 주세요.\n");
         MessageBox(NULL,WarningString,"해킹 프로그램 발견",MB_ICONSTOP);
         CloseHandle(hProcess);
         ExitProcess(-1);
        }
         }
        }
       }
      }
      free(newbuf);
      *((PDWORD)&p) += (DWORD)struct_mbi.RegionSize;
    }while(p < struct_si.lpMaximumApplicationAddress);
  }
      CloseHandle(hProcess);
 }
 return TRUE;
}


실제로 실행해보면 알 수 있지만, ReadProcessMemory()를 수행하는 것은 꾀 시간을
많이 소요하는 작업입니다. 이렇게 하는 것보다는 Dll을 모든 프로세스에 인젝션 시키신 후,
각 프로세스에 인젝션된 Dll에서 메모리 검사를 하게되면, 같은 프로세스 영역 내임으로,
ReadProcessMemory()도 필요 없으며, 분할처리가 가능해져, 그 속도 역시 빨라 집니다.
Dll을 인젝션 하는 방식의 코드는 별도로 코드를 첨부하도록 하겠습니다.

Finding Named Object기법의 경우는 창이름 이나 클레스 이름은 EnumWindow 함수를
돌면서 GetWindowText(), GetClassName()함수를 이용하여 구하여 비교하는 방식을
쓰면 됩니다. 코드는 다음과 같습니다.

char szWindowDataBase[][30] = {"CheatEngine",
         "AutoPlay",
         "GameHack",
         "Memory Search",
         "TSearch"};
char szClassDataBase[][30] = {"CheatEngine",
         "AutoPlay",
         "GameHack",
         "Memory Search",
         "TSearch"};
int cnt,cnt2;
BOOL CALLBACK EnumWinProc(HWND hwnd,LPARAM lparam)
{
   char szWindow[255];
   char szClass[255];
 
   if(GetParent(hwnd)) return TRUE;
   GetWindowText(hwnd,szWindow,255);
   GetClassName(hwnd,szClass,255);
  
   for(int i = 0; i < cnt; i++)
   {
   if(!strnicmp(szWindowDataBase[i],szWindow,strlen(szWindowDataBase[i])))
   {
  MessageBox(NULL,"게임 해킹 프로그램 발견 되었습니다.\n게임이 종료 됩니다.\n","해킹 프로그램 발견",MB_ICONSTOP);
  ExitProcess(-1);
   }
   }
   for(i = 0; i < cnt; i++)
   {
   if(!strnicmp(szClassDataBase[i],szClass,strlen(szClassDataBase[i])))
   {
  MessageBox(NULL,"게임 해킹 프로그램 발견 되었습니다.\n게임이 종료 됩니다.\n","해킹 프로그램 발견",MB_ICONSTOP);
  ExitProcess(-1);
   }
   }
   return TRUE;
}
BOOL FindBadWindowOrClass()
{
    for(cnt = 0; ;cnt++)    //Counting Pattern
      if(!szWindowDataBase[cnt][0])
           break;
    for(cnt2 = 0; ;cnt2++)    //Counting Pattern
      if(!szWindowDataBase[cnt2][0])
           break;
 EnumWindows(EnumWinProc,NULL);
 return TRUE;
}

프로세스 이름의 경우 EnumWindow 콜백에서 GetThreadProcessId() 함수를 한 후,
OpenProcess() 하여주고, GetModuleBaseName()함수를 이용하여 프로세스 이름을
구하여 확인시켜 주는 방식으로 진행하여 주면 됩니다. 이 코드는 패턴 검사의 코드를
조금 수정하면 됨으로 따로 올리진 않겠습니다. 그 나머지 요소는 GH 프로그램이
사용하고 있는 요소들을 어떻게 확인하는지 Process Explorer를 이용한 예제를 보여드
리 겠습니다.

사용자 삽입 이미지

먼저 위와 같이 Lower panel view를 Handles로 해줍니다.

사용자 삽입 이미지

TSearch에서 사용중인 핸들 목록을 볼 수 있는데요.
위 그림에서 보면, TSearch는 3가지의 독특한 Event를 만드는 것을 알 수 있습니다.
즉, 다음 3가지 중 하나를 선택하여 해당 이벤트가 존재하는지를 확인한다면,
TSearch의 실행여부를 확인할 수 있습니다. 코드는 다음과 같습니다.

BOOL CheckByEventName()
{
 char szEventDataBase[][30] = {
         "User stopped search",
         "Debugger Loaded",
         "TSearch.ServerLoaded"
        };
 HANDLE hEvent;
  for(int cnt = 0; ;cnt++)    //Counting Pattern
      if(!szEventDataBase[cnt][0])
           break;
  for(int i = 0; i < cnt; i++)
  {
 if(OpenEvent(EVENT_ALL_ACCESS,FALSE,szEventDataBase[i]))
 {
    MessageBox(NULL,"게임 해킹 프로그램 발견 되었습니다.\n게임이 종료 됩니다.\n","해킹 프로그램 발견",MB_ICONSTOP);
       ExitProcess(-1);
 }
  }
  return TRUE;
}

뮤텍스를 이용한 확인 방법의 코드는 다음과 같습니다.

BOOL CheckByMutexName()
{
 char szMutexDataBase[][30] = {
         "TSearch",
         "CheatEngine",
         "GameHack"
        };
 HANDLE hEvent;
  for(int cnt = 0; ;cnt++)    //Counting Pattern
      if(!szMutexDataBase[cnt][0])
           break;
  for(int i = 0; i < cnt; i++)
  {
 CreateMutex(NULL,FALSE,szMutexDataBase[i]);
 if(GetLastError() == ERROR_ALREADY_EXISTS)
 {
    MessageBox(NULL,"게임 해킹 프로그램 발견 되었습니다.\n게임이 종료 됩니다.\n","해킹 프로그램 발견",MB_ICONSTOP);
       ExitProcess(-1);
 }
  }
  return TRUE;
}

파일맵을 이용한 방법의 코드는 다음과 같습니다.

BOOL CheckByFileMapName()
{
 char szFileMapDataBase[][30] = {"DUALMEM",
         "TSearch",
         "CheatEngine",
         "GameHack"
        };
 HANDLE hFileMap;
 LPVOID pMapFile;
  for(int cnt = 0; ;cnt++)    //Counting Pattern
      if(!szFileMapDataBase[cnt][0])
           break;
  for(int i = 0; i < cnt; i++)
  {
 hFileMap = CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE,NULL,
      PAGE_READWRITE,0,1,szFileMapDataBase[i]);
 if(GetLastError() == ERROR_ALREADY_EXISTS)
 {
    MessageBox(NULL,"게임 해킹 프로그램 발견 되었습니다.\n게임이 종료 됩니다.\n","해킹 프로그램 발견",MB_ICONSTOP);
       ExitProcess(-1);
 }
  }
  return TRUE;
}

레지스트리, 파일로 확인하는 방법은 어떤 레지스트리나 파일을 쓰는지는 Process
Explorer를 확인하는 것으로 동일하고, 확인은 레지스트리나 파일을 열 떄,
이미 존재하는지 여부만 확인해주면 됨으로 별도의 코드는 첨부하지 않겠습니다.
윈도우즈에 로드되어 있는 드라이버의 목록은 ntdll.dll의
ZwQuerySystemInformation() 를 이용하여 구할 수 있습니다.

참고적으로 위의 핸들목록을 출력하는 기능은 정덕영님의 저서 'Windows 구조와
원리 그리고 Codes'에 나온 코드인 ListHandles라는 코드도 똑같은 기능을 합니다.
코드는 다음과 같습니다.

#include "stdafx.h"
#include "windows.h"
#include <stdio.h>
#include "nativeAPI.h"
BOOL EnablePrivilege(PCSTR name)
{
    TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
    LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);
    HANDLE hToken;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
    AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
    BOOL rv = GetLastError() == ERROR_SUCCESS;
    CloseHandle(hToken);
    return rv;
}

int main(int argc, char* argv[])
{
    ULONG pid;
 HANDLE hProcess, hCurrentProcess;
 SYSTEM_HANDLE_INFORMATION  *aHandles;
 ULONG  nHandles, nCount;
 ULONG  *pULONG;
 
 //1. Parameter parsing
    if (argc == 1)
 {
  printf("HELP : ListHandles PID\n");
  return 0;
 }
 pid = strtoul(argv[1], 0, 0);
 //2. Get process handle
    EnablePrivilege(SE_DEBUG_NAME);
    hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
 hCurrentProcess = GetCurrentProcess();
 //3. Get Handle's Information
    nCount = 100;
    pULONG = (PULONG)malloc(nCount * sizeof(SYSTEM_HANDLE_INFORMATION) + sizeof(ULONG));
    while (ZwQuerySystemInformation(SystemHandleInformation, pULONG,
    nCount * sizeof(SYSTEM_HANDLE_INFORMATION)+ sizeof(ULONG)
    , 0) == STATUS_INFO_LENGTH_MISMATCH)
 {
  free(pULONG);
  nCount += 50;
  pULONG = (PULONG)malloc(nCount * sizeof(SYSTEM_HANDLE_INFORMATION) + sizeof(ULONG));
 }
 nHandles = *pULONG;
 aHandles = (PSYSTEM_HANDLE_INFORMATION)(pULONG + 1);
 
 //4. Print Handle's Information
 printf("Process ID : %x\n", pid);
    for (ULONG i = 0; i < nHandles; i++)
 {
        if (aHandles[i].ProcessId == pid)
  {
   HANDLE hObject;
   OBJECT_BASIC_INFORMATION obi;
   POBJECT_TYPE_INFORMATION pOti;
   POBJECT_NAME_INFORMATION pOni;
   ULONG nTypeName, nObjectName, n;
   if(DuplicateHandle(hProcess, (HANDLE)aHandles[i].Handle,
    hCurrentProcess, &hObject, 0, 0, DUPLICATE_SAME_ACCESS) == FALSE)
    continue;
            ZwQueryObject(hObject, ObjectBasicInformation, &obi, sizeof(obi), &n);
            printf("%p %04hx %3lx %3ld %4ld ",
                   aHandles[i].Object, aHandles[i].Handle, obi.Attributes,
                   obi.HandleCount - 1, obi.PointerCount - 2);
   //Object Type
            nTypeName = obi.TypeInformationLength + 2;
            pOti = (POBJECT_TYPE_INFORMATION)malloc(nTypeName);
            ZwQueryObject(hObject, ObjectTypeInformation, pOti, nTypeName, &nTypeName);
            printf("%-14.*ws ", pOti->Name.Length / 2, pOti->Name.Buffer);
   //Object Name
            nObjectName = obi.NameInformationLength == 0
                ? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
             pOni = (POBJECT_NAME_INFORMATION)malloc(nObjectName);
           
            if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, pOni,
       nObjectName, &nObjectName)))
                printf("%.*ws", pOni->Name.Length / 2, pOni->Name.Buffer);
            printf("\n");
   
   free(pOni); free(pOti); CloseHandle(hObject);
        }
    }
    free(aHandles);
    CloseHandle(hProcess);
    return 0;
}


세번쨰로 자동 플레이 차단은 에플리케이션 방식의 오토플레이라면 유저레벨에서
막는방법과 커널레벨에서 막는 방법으로 나뉠 수 있습니다. 사실 후킹하는 시점이
다를 뿐, 실제적으로 차단해야할 API들은 같습니다. 유저레벨에서는 모든 프로세스에
Dll을 인젝션 한 후, 해당 Dll에서 GetPixel(), PostMessageA(), PostMessageW(),
SendInput(), SendMessageA(), SendMessageW(), SetCursorPos(), keybd_event(),
mouse_event() 등의 함수를 차단하여 주어야 합니다.
커널레벨에서는 KeServiceDescriptorTableShadow에 있는 SendInput(),
NtUserQueryWindow(), NtUserBuildHwndList(), NtUserFindWindowEx(),
NtUserGetForegroundWindow(), GetDC(), GetWindowDC() 등의 함수를 후킹해서
처리해 주어야 합니다.  그래픽 관련 함수를 후킹하는 이유는 최근 오토플레이들은
단순한 메크로가 아닌, 픽셀 정보를 읽어온 후, 그에 interact하여 작동하는 방식을
많이 취하기 떄문입니다. 위의 함수들을 모두 후킹하여 처리하여 주면, 에플리케이션
방식의 메크로는 거의 차단된다고 보시면 됩니다. (커널레벨에서의 irp 발생 및
pesudo 코드 사용등 예외는 존재합니다.)

네번쨰로 메시지 후킹 차단은 커널단에서 비교적 강력하게 구현될 수 있는데,
메시지 후킹은 SetWindowHookEx()를 이용해서 이루어 지는데, 운영체제 내에서는
다음과 같은 구조체로 관리 되어 집니다.
#define CWINHOOKS       (WH_MAX - WH_MIN + 1)
typedef struct tagPROCESSINFO * PPROCESSINFO;
typedef struct tagDESKTOP * PDESKTOP;
typedef struct tagDESKTOPINFO * PDESKTOPINFO;
typedef struct tagTHREADINFO * PTHREADINFO;
typedef struct tagHOOK * PHOOK;
typedef HWND * PWND;
typedef struct _HEAD {
//    KHANDLE h;
 DWORD   h;
    DWORD   cLockObj;
} HEAD, *PHEAD;
typedef struct _THROBJHEAD {
    HEAD a;
    PTHREADINFO pti;
} THROBJHEAD, *PTHROBJHEAD;
typedef struct _DESKHEAD {
    PDESKTOP rpdesk;
//    KPBYTE   pSelf;
 PVOID    pSelf;
} DESKHEAD, *PDESKHEAD;
typedef struct _THRDESKHEAD {
    THROBJHEAD a;
    DESKHEAD b;
} THRDESKHEAD, *PTHRDESKHEAD;
typedef struct tagHOOK {   /* hk */
    THRDESKHEAD     head;
    PHOOK           phkNext;
    int             iHook;              // WH_xxx hook type
    PVOID           offPfn;
    UINT            flags;              // HF_xxx flags
    int             ihmod;
    PTHREADINFO     ptiHooked;          // Thread hooked.
    PDESKTOP        rpdesk;             // Global hook pdesk. Only used when
                                     //  hook is locked and owner is destroyed
} HOOK;
typedef struct tagDESKTOPINFO {
    PVOID  pvDesktopBase;          // For handle validation
    PVOID  pvDesktopLimit;         // ???
    PWND          spwnd;                 // Desktop window
    DWORD         fsHooks;                // Deskop global hooks
    PHOOK         aphkStart[CWINHOOKS + 1];  // List of hooks
    PWND          spwndShell;            // Shell window
    PPROCESSINFO  ppiShellProcess;        // Shell Process
    PWND          spwndBkGnd;            // Shell background window
    PWND          spwndTaskman;          // Task-Manager window
    PWND          spwndProgman;          // Program-Manager window
    PVOID         pvwplShellHook;         // see (De)RegisterShellHookWindow
    int           cntMBox;                // ???
} DESKTOPINFO;
typedef struct _CLIENT_ID
{
 HANDLE UniqueProcess;
 HANDLE UniqueThread;
} CLIENT_ID;
#pragma packed(1)
typedef struct tagTHREADINFO {
 struct W32THREAD // dt win32k!_W32THREAD -r
 {
  PVOID pEThread;
  unsigned long RefCount;
  PVOID ptlW32;
  PVOID pgdiDcattr;
  PVOID pgdiBrushAttr;
  PVOID pUMPDObjs;
  PVOID pUMPDHeaps;
  unsigned long dwEngAcquireCount;
  PVOID pSemTable;
  PVOID pUMPDObj;
 } W32THREAD;
//***************************************** begin: USER specific fields
    PVOID             ptl;                // Listhead for thread lock list
 // end :: 0x2c :: start
    PPROCESSINFO    ppi;                // process info struct for this thread
    PVOID              pq;                 // keyboard and mouse input queue
    PVOID             spklActive;         // active keyboard layout for this thread
    PVOID             pcti;             // Info that must be visible from client
    PDESKTOP        rpdesk;
    PDESKTOPINFO    pDeskInfo;          // Desktop info visible to client
 // ....omitted....
} THREADINFO, *PTHREADINFO;
typedef struct _TEB
{
   NT_TIB Tib;                         // 00h
   PVOID EnvironmentPointer;           // 1Ch
   CLIENT_ID Cid;                      // 20h
   PVOID ActiveRpcInfo;                // 28h
   PVOID ThreadLocalStoragePointer;    // 2Ch
   PVOID Peb;                           // 30h
   DWORD LastErrorValue;               // 34h
   DWORD CountOfOwnedCriticalSections; // 38h
   PVOID CsrClientThread;              // 3Ch
   PTHREADINFO Win32ThreadInfo;        // 40h
   DWORD Win32ClientInfo[0x1F];        // 44h
   PVOID WOW32Reserved;                // C0h
   DWORD CurrentLocale;                // C4h
   DWORD FpSoftwareStatusRegister;     // C8h
   PVOID SystemReserved1[0x36];        // CCh
   PVOID Spare1;                       // 1A4h
   LONG ExceptionCode;                 // 1A8h
   DWORD SpareBytes1[0x28];            // 1ACh
   PVOID SystemReserved2[0xA];         // 1D4h
//   GDI_TEB_BATCH GdiTebBatch;          // 1FCh
   DWORD gdiRgn;                       // 6DCh
   DWORD gdiPen;                       // 6E0h
   DWORD gdiBrush;                     // 6E4h
   CLIENT_ID RealClientId;             // 6E8h
   PVOID GdiCachedProcessHandle;       // 6F0h
   DWORD GdiClientPID;                 // 6F4h
   DWORD GdiClientTID;                 // 6F8h
   PVOID GdiThreadLocaleInfo;          // 6FCh
   PVOID UserReserved[5];              // 700h
   PVOID glDispatchTable[0x118];       // 714h
   DWORD glReserved1[0x1A];            // B74h
   PVOID glReserved2;                  // BDCh
   PVOID glSectionInfo;                // BE0h
   PVOID glSection;                    // BE4h
   PVOID glTable;                      // BE8h
   PVOID glCurrentRC;                  // BECh
   PVOID glContext;                    // BF0h
   DWORD LastStatusValue;           // BF4h
   UNICODE_STRING StaticUnicodeString; // BF8h
   WCHAR StaticUnicodeBuffer[0x105];   // C00h
   PVOID DeallocationStack;            // E0Ch
   PVOID TlsSlots[0x40];               // E10h
   LIST_ENTRY TlsLinks;                // F10h
   PVOID Vdm;                          // F18h
   PVOID ReservedForNtRpc;             // F1Ch
   PVOID DbgSsReserved[0x2];           // F20h
   DWORD HardErrorDisabled;            // F28h
   PVOID Instrumentation[0x10];        // F2Ch
   PVOID WinSockData;                  // F6Ch
   DWORD GdiBatchCount;                // F70h
   DWORD Spare2;                       // F74h
   DWORD Spare3;                       // F78h
   DWORD Spare4;                       // F7Ch
   PVOID ReservedForOle;               // F80h
   DWORD WaitingOnLoaderLock;          // F84h
} TEB, *PTEB;


TEB의 Win32ThreadInfo 구조체의 pDeskInfo에 aphkStart라는 배열이
훅을 관리하는데, 즉 이 배열을 주기적으로 0으로 초기화 시킴으로써 설치된 훅을
제거할수도 있으며 메시지 후킹을 차단할수도 있습니다.

다섯번쨰로 필요한 기능으로써, 허용되지 않은 메모리 접근차단은 유저레벨에서는
각 프로세스에 Dll을 인젝션 한 후, NtOpenProcess(), NtProtectVirtualMemory(),
NtReadVirtualMemory(), NtWriteVirtualMemory(), ZwOpenProcess(), ZwProtect
VirtualMemory(), ZwReadVirtualMemory(), ZwWriteVirtualMemory(),
OpenProcess(), ReadProcessMemory(), VirtualProtect(), VirtualProtectEx(),
WriteProcessMemory(), GetWindowThreadProcessId()등의 API를 후킹하여
주어야 합니다. 유저레벨에서의 후킹코드는 앞에서 다뤘던 코드에 조금의 수정을
가하면 되는 것임으로, 생략하도록 하겠습니다. 커널레벨에서의 후킹코드들은
다음과 같습니다.

ZwOpenProcess Hook :

NTSTATUS NewZwOpenProcess(
    OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PCLIENT_ID ClientId OPTIONAL
)
{
    NTSTATUS rc;
    NTSTATUS rc2;
    CHAR Caller_Process_Name[PROCNAMELEN];
    CHAR Target_Process_Name[PROCNAMELEN];
    PEPROCESS Process;
    char *nameptr;
    
    GetProcessName( Caller_Process_Name );  //Get Process Name
    rc = ((ZWOPENPROCESS)(OldZwOpenProcess)) (
   ProcessHandle,
   DesiredAccess,
   ObjectAttributes,
   ClientId OPTIONAL); 
 
 if(DesiredAccess == PROCESS_ALL_ACCESS)
 {
  if(NT_SUCCESS(rc))    
  {       
   
   rc2 = ObReferenceObjectByHandle(
      *ProcessHandle,
      PROCESS_ALL_ACCESS,
      NULL,
      KernelMode,
      (void *)&Process,
      NULL);
   if(NT_SUCCESS(rc2))
   {
    nameptr = (PCHAR)Process + gProcessNameOffset;
    strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
    Target_Process_Name[NT_PROCNAMELEN] = 0;
    if(!strncmp(Target_Process_Name,MYPROCESS,strlen(MYPROCESS)))
    {
     ObDereferenceObject(Process);
     ZwClose(ProcessHandle);
     rc = STATUS_INVALID_HANDLE;
     ProcessHandle = 0;
    }
   }
  }
 }
    return rc;
}

ZwOpenProcess() 함수를 후킹하고 있다가, 만약 핸들을 오픈하고자 하는 프로세스가,
보호하는 프로세스라면 핸들을 닫고 잘못된 핸들이라고 값을 리턴합니다.

ZwWriteVirtualMemory Hook :

NTSTATUS NTAPI NewZwWriteVirtualMemory(
 IN HANDLE hProcess,
 IN PVOID BaseAddress,
 IN PVOID Buffer,
 IN ULONG BytesToWrite,
 OUT PULONG BytesWritten
)
{
 NTSTATUS rc;
 NTSTATUS rc2;
                  CHAR Attack_Process_Name[PROCNAMELEN];
 CHAR Target_Process_Name[PROCNAMELEN];
 PEPROCESS Process;
 char *nameptr;
 GetProcessName( Caller_Process_Name );
 rc2 = ObReferenceObjectByHandle(
     hProcess,
     PROCESS_ALL_ACCESS,
     NULL,
     KernelMode,
     (void *)&Process,
     NULL);
 if(NT_SUCCESS(rc2))
 {
  nameptr = (PCHAR)Process + gProcessNameOffset;
  strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
  Target_Process_Name[NT_PROCNAMELEN] = 0;
  ObDefreferenceObject(Process);
  if(!strncmp(Target_Process_Name,MYPROCESS,strlen(MYPROCESS)))
  {
   return STATUS_UNSUCCESSFUL;
  }
 }
 rc = ((ZWWRITEVIRTUALMEMORY)(OldZwWriteVirtualMemory)) (
  hProcess,
  BaseAddress,
  Buffer,
  BytesToWrite,
  BytesWritten);
 return rc;
}


ZwReadVirtualMemory Hook :

NTSTATUS NTAPI NewZwReadVirtualMemory(
 IN HANDLE hProcess,
 IN PVOID BaseAddress,
 OUT PVOID Buffer,
 IN ULONG BytesToRead,
 OUT PULONG BytesRead
)
{
 NTSTATUS rc;
  NTSTATUS rc2;
                  CHAR Caller_Process_Name[PROCNAMELEN];
 CHAR Target_Process_Name[PROCNAMELEN];
 PEPROCESS Process;
 char *nameptr;
 GetProcessName( Caller_Process_Name ); 
 rc2 = ObReferenceObjectByHandle(
     hProcess,
     PROCESS_ALL_ACCESS,
     NULL,
     KernelMode,
     (void *)&Process,
     NULL);
 if(NT_SUCCESS(rc2))
 {
  nameptr = (PCHAR)Process + gProcessNameOffset;
  strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
  Target_Process_Name[NT_PROCNAMELEN] = 0;
  ObDefreferenceObject(Process);
  if(!strncmp(Target_Process_Name,MYPROCESS,strlen(MYPROCESS)))
  {
   {
    return STATUS_INVALID_HANDLE;
   }
  }
 }
 
 rc = ((ZWREADVIRTUALMEMORY)(OldZwReadVirtualMemory)) (
   hProcess,
   BaseAddress,
   Buffer,
   BytesToRead,
   BytesRead);
 return rc;
}

여섯번쨰로 디버깅 차단은 코드에 안티 디버깅 루틴을 삽입과 후킹을 사용합니다.
안티 디버깅 루틴을 먼저 다루어 보면,
첫번쨰로 IsDebuggerPresent() 함수를 이용한 방법이 있는데,
IsDebuggerPresent()함수는 kernel32.dll에 의해 export되어지는 함수로써,
해당 함수를 호출한 프로세스가 디버깅 당하는 중이면 TRUE(1)을,
아닐 경우는 FALSE(0)을 반환하는 함수이다. 즉 이 함수를 주기적으로 호출하여
줌으로써 디버깅 여부를 확인할 수 있다. 코드는 다음과 같습니다.

if(IsDebuggerPresent())
{
    OutputDebugString("Debugeed!!");
    //디버깅 당하는 중일떄의 어떠한 처리
}

두번쨰 방법으로 PEB 구조체의 BeingDebuggged 값을 직접 조작하는 방법이 있다.
IsDebuggerPresent()함수는 내부적으로, PEB의 BeingDebugged값을 읽어서 리턴
하여 주는 함수입니다. 즉 IsDebuggerPresent()함수를 호출하지 않고, 직접
PEB의 BeingDebugged의 값을 읽어와도 결과는 같다는 소리입니다.
다음은 PEB의 BeingDebugged의 값을 읽어오는 함수 입니다.

BOOL Pesudo_IsDebuggerPresent()
{
BOOL Retval = 0;
  __asm
  {
      push eax
      mov eax,dword ptr fs:{0x18]
      mov eax,dword ptr ds:[eax+0x30]
      movzx eax,byte ptr ds:[eax+0x2]
      mov Retval,eax
     pop eax
  }
  return Retval;
}

세번쨰 방법으로 CheckRemoteDebuggerPresent() 함수를 이용하는 방법이 있습니다.
이 함수는 함수를 호출하는 프로세스 자신외에도, 타 프로세스에도 사용이 가능합니다.
다음과 같이 사용합니다.

BOOL CheckDebugger(HANDLE hProcess)

{
     BOOL Retval = 0;
 
     CheckRemoteDebuggerPresent(hProcess,&Retval);
     return Retval;
}

* CheckRemoteDebuggerPresent()는 NTAPI의 ZwQueryInformationProcess()로
연결됩니다. ZwQueryInformationProcess()는 다음과 같은 호출 인자를 갖는 함수입니다.

NTSTATUS NTAPI ZwQueryInformationProcess(HANDLE ProcessHandle,
    PROCESSINFOCLASS ProcessInformationClass,
    PVOID ProcessInformation,
    ULONG ProcessInformationLength,
    PULONG ReturnLength);

첫번쨰는 질의 하고자 하는 대상 프로세스의 핸들.
두번쨰는 질의 하고자 하는 내용(디버깅 여부는 ProcessDebugPort)
세번쨰는 결과
네번쨰는 길이
다섯번쨰는 실반환 길이이다.
해당 함수를 직접 호출하는 것도 하나의 방법이 될 수 있을 것입니다.

네번쨰 방법으로 NtGlobalFlag의 값을 확인하는 방법이 있다.
디버거가 프로세스를 디버깅 할때는, 셋되어 지는 Flag들이 있는데, NtGlobalFlag는
그 중 하나이다. 코드는 다음과 같습니다.

BOOL CheckNtGlobalFlag()
{
  BOOL Retval = 0;

  __asm
  {
        push eax
        mov eax,dword ptr fs:[0x30]
         mov eax,0x68
         mov eax,dword ptr ds:[eax]
         cmp eax,0x70
        pop eax
        jne NotDebuged
         mov Retval,1
NotDebugged :
         nop
    }
    return Retval;
}

다섯번쨰 방법으로 Heap flags를 이용하는 방법이 있습니다. Heap의 상태가 디버그
되지 않고 있는 평소 상태와 다른지를 확인하는 것은 강력한 안티디버그 메소드가 될
수 있습니다. 예를들면, 힙 해더에 있는 ForceFlags(오프셋 0x10)은 디버거의 존재
여부를 확인하기 위해 쓰일 수 있습니다.대략적인 코드는 다음과 같습니다.

mov eax, fs:[30h]
mov eax, [eax+18h] ;process heap
mov eax, [eax+10h] ;heap flags
test eax, eax
jne @DebuggerDetected

여섯번쨰 방법으로 UnhandledExceptionFilter를 이용하는 방법이 있습니다.
SEH 핸들러의 주소로 디버거가 없을시 실행할 코드로 넣어주고,
고의적으로 예외를 발생시키어, 디버거가 있는지 없는지를 확인하여 주는
방법입니다. (디버거가 존재함으로, SEH 핸들러로 넘어 가지 않고, 다음 명령을
실행 시키게 되는점을 이용) 코드는 다음과 같습니다.

push @not_debugged
call SetUnhandledExceptionFilter
xor eax, eax
mov eax, dword [eax] ; trigger exception
;program terminated if debugged
;...
@not_debugged:
;process the exception
;continue the execution
;...

일곱번째로 NtSetInformationThread를 이용하는 방법이 있습니다. ThreadInformationClass 가 0x11 (ThreadHideFromDebugger 상수)로 지정되고
호출되면, 스레드는 디버거로부터 분리 될 것입니다. (ThreadHideFromDebugger는
ETHREAD의 필드중에 하나죠.) 코드는 다음과 같습니다.

Example:
push 0
push 0
push 11h ;ThreadHideFromDebugger
push -2
call NtSetInformationThread
;thread detached if debugged
;...

여덟번쨰로 kernel32!CloseHandle and NtClose 를 이용하는 방법이 있습니다.
프로세스가 디버그될 떄, ZwClose() 를 잘못된 핸들을 주고 호출하는 것은
STATUS_INVALID_HANDLE(0xC0000008) 예외를 발생 시킵니다.
디버깅 당하고 있다면, CloseHandle()를 호출하는 다음줄의 코드를 발생시킬 것이고,
디버깅 되고 있지 않다면, SEH핸들러가 호출될 것임을 이용한 방법입니다.
코드는 다음과 같습니다.

push offset @not_debugged
push dword fs:[0]
mov fs:[0], esp
push 1234h ;invalid handle
call CloseHandle
; if fall here, process is debugged
;...
@not_debugged:
;...

아홉번쨰로 OutputDebugStringA를 이용하는 간단한 방법도 있습니다.
OutputDebugString()함수가 성공적으로 수행되는지, 안되는지 (리턴값)을 확인하는
방법입니다. 코드는 다음과 같습니다.

xor eax, eax
push offset szHello
call OutputDebugStringA
cmp eax, 1
jne @DebuggerDetected
...

앞서 말한 방법들을 모두 TLS Callback으로써 등록하여 작동시킬수도 있습니다.
TLS Callback은 스텔스하게 안티 디버그 코드를 실행시킬 수 있는 방법으로 사용될
수 있는데, 단지 안티 디버그 코드를 프로그램에 넣어놓고, 헥스 에디터등을 이용하여
PE해더의 Thread Local Storage entry (PE optional header에서 10번째 디렉토리 엔트리
에 있는) 의 값을 코드의 주소로 바꾸어줌으로써, 안티 디버그 코드가 프로그램의
엔트리 포인트가 실행되기전에, 실행 되도록 만들어 줄 수 있습니다.

열번째 방법으로 커널레벨에서 확인하는 방법으로써,  보호하고자 하는 프로세스의
EPROCESS에 debug port의 값을 확인하는 방법이 있습니다. debug port의 값은
디버깅 되고 있지 않을떄는 0이며, 디버깅 될때에는 0이 아닙니다. 이 점을 이용해서
디버깅 여부를 확인하고 싶은 프로세스의 EPROCESS 스트럭쳐의 debug port값을
확인하는 것은 아주 강력한 안티 디버그 방법으로서 사용될 수 있습니다.
이 밖에도 훨씬 많은 안티 디버깅 방법들이 존재하며,
나머지 목록및 더 자세한 설명은 다음페이지를 참조하시기 바랍니다.
http://dual5651.hacktizen.com/tt/entry/Windows-Anti-Debug-Reference

이렇게 많은 안티 디버깅 루틴이 존재하지만, 안티 디버깅 루틴만으로 충분한 것은
아닙니다. 위에서 말했듯이, 후킹 역시 중요한 부분을 차지 합니다.
DebugActiveProcess() 같은 함수를 필수적으로 후킹해 주어서 디버거가 붙는
자체를 차단해 주어야 합니다. 또 게임을 바로 실행시키는 방식이 아닌,
로더를 거치는 방식을 사용하여, CreateProcess()에 DEBUG_ONLY_THIS_PROCESS
같은 옵션을 가지고 임으로 사용되는 것을 막아주어야 합니다.

여덟번쨰로 필요한 기능인 무결성 검사의 코드는 다음과 같습니다.

#include "stdafx.h"
#include <windows.h>
int main(int argc, char* argv[])
{
 int a;
 DWORD checksum = 0xE1E4CDE2;
 __asm
 {
  pushad
  pushfd
  mov esi,offset StartAddressOfCheck
  mov ecx,offset EndAddressOfCheck
  sub ecx,offset StartAddressOfCheck
  xor eax,eax
  xor ebx,ebx
  Check_Loop:
    mov ebx, [esi]
    add eax,ebx
    rol eax,1
    inc esi
    loop Check_Loop
 
    cmp eax,checksum
    jne EndAddressOfCheck //코드 조작 감지
    popfd
    popad
 }
StartAddressOfCheck:
 a = 5;
 if(a > 10)
 {
  MessageBox(NULL,"You beat this program!!","Congratulation",64);
  return 0;
 }
 else
 {
  MessageBox(NULL,"a 변수의 값이 10보다 작습니다.","ashole!",MB_ICONWARNING);
  return 0;
 }
EndAddressOfCheck:
 __asm
 {
  popfd
  popad
 }
 MessageBox(NULL,"You can`t beat this program sxxker!!","Cracker!!",MB_ICONWARNING);
 return 0;
}

StartAddressOfCheck 로 부터 EndAddressOfCheck 까지의 명령어들의 합산값을
미리 계산하여 두고, 프로그램을 실행할 떄에, 그값이 기존의 값과 같은지 여부를
확인하여 변조되었는지를 확인하는 방법입니다. 이 확인하는 루틴을 별도의 스레드를
만들어 와일을 돌리거나, 타이머를 이용하는 방법으로, 코드의 지속적인 감시도 가능합니다.
단, 명령코드의 합산은 현재 코드가 존재하는 주소에 의해서도 영향을 받기 떄문에,
컴파일 모드가 디버그 인지, 릴리즈 인지, StartAddressOfCheck앞에 새로운 코드나
문자열등 StartAddressOfCheck의 주소에 영향을 줄 수 있는 변수가 있으면, 새롭게
checksum 값을 계산하여 상수값으로 주어야 합니다. 다소 귀찮은 면이 있지만,
프로그램을 안전하게 보호하는데 한 역활을 할 수 있습니다. 위의 코드는 프로세스에
대한 검사이지만, 파일에 대해서도 쉽게 적용할 수 있을 것입니다. (ReadFile())
또, 조금만 생각해보면, 게임에 무결성 체크 코드를 넣지 않아도, Anti GH 프로그램에서
ReadProcessMemory()함수를 이용하여 체크할수도 있을 것입니다.

아홉번쨰로 필요한 기능인 시스템 디스크립터 복구이 의미하는 것은 Rootkit에
의해 변조되어 있을, 디스크립터들(ex: SSDT, IDT, and so on..)을 의미 합니다.
SSDT 나 IDT의 변조여부는 어떻게 확인하는가? 원리는 간단합니다.
SSDT나 IDT는 기본적으로 ntoskrnl.exe의 메모리 영역에 속함으로,
각 모듈들의 시작주소와 끝주소들을 구해놓고, 만약 백터나 디스패쳐의 주소가
ntoskrnl.exe의 시작주소와 끝주소 사이에 있지 않다면, 이는 변조된 것으로
판단하면 됩니다. 코드는 다음과 같습니다.

PMODULE_LIST GetListOfModules(PNTSTATUS pns)
{
    ULONG ul_NeededSize;
    ULONG *pul_ModuleListAddress = NULL;
    NTSTATUS     ns;
    PMODULE_LIST pml = NULL;
 
    // Call it the first time to determine the size required
    // to store the information.
    ZwQuerySystemInformation(SystemModuleInformation,
                             &ul_NeededSize,
                             0,
                             &ul_NeededSize);
    pul_ModuleListAddress = (ULONG *) ExAllocatePool(PagedPool, ul_NeededSize);
 
    if (!pul_ModuleListAddress) // ExAllocatePool failed.
    {
        if (pns != NULL)
 
          *pns = STATUS_INSUFFICIENT_RESOURCES;
 
        return (PMODULE_LIST) pul_ModuleListAddress;
    }
 
    ns = ZwQuerySystemInformation(SystemModuleInformation,
                                  pul_ModuleListAddress,
                                  ul_NeededSize,
                                  0);
    if (ns != STATUS_SUCCESS)// ZwQuerySystemInformation failed.
    {
        // Free allocated paged kernel memory.
        ExFreePool((PVOID) pul_ModuleListAddress);
        if (pns != NULL)
 
           *pns = ns;
        return NULL;
    }
    pml = (PMODULE_LIST) pul_ModuleListAddress;
 
    if (pns != NULL)
 
       *pns = ns;
    return pml;
}

..................

   g_pml = GetListOfModules(&ns);
   if(!g_pml)
   {
    DbgPrint("Get Failed");
    return;
   }
    for(count = 0; count < g_pml->d_Modules; count++)
 {
  if(!_stricmp("ntoskrnl.exe",g_pml->a_Modules[count].a_bPath+g_pml->a_Modules[count].w_NameOffset))
  {
   g_NTOSKRNL.Base = (ULONG)g_pml->a_Modules[count].pBase;
   g_NTOSKRNL.End = ((ULONG)g_pml->a_Modules[count].pBase + g_pml->a_Modules[count].d_Size);
  }
 }

위의 코드로 ntoskrnl.exe의 시작주소와 끝주소를 알 수 있으며, SSDT와 IDT를
끝번호까지 돌면서, ntoskrnl.exe에 속하는지만 확인하여 주면 됩니다.
만약, 이런식으로 루프를 돌다가 변조된 것이 발견되면 어떻게 복구해야할까요?
그것에 대해서는
http://dual5651.hacktizen.com/tt/entry/SSDT-후킹-무력화에-대한-연구
의 SSDT Restore에 대해서 읽어보시고, 코드를 참조하시면 됩니다.

목차에는 없지만 최근 많이 사용되고 있는 프로세스 숨기기에 대해서도 간단히
다루어 보겠습니다. 첫번째로 사용할 수 있는 방법으로서 커널단에서
ZwQuerySystemInformation() 이라는 함수를 후킹하는 방법이 있습니다.
코드는 다음과 같습니다.

NTSTATUS NTAPI NewZwQuerySystemInformation(
            IN ULONG SystemInformationClass,
   IN PVOID SystemInformation,
   IN ULONG SystemInformationLength,
   OUT PULONG ReturnLength
)
{
 NTSTATUS rc;
 CHAR Attack_Process_Name[PROCNAMELEN];
 
 GetProcessName( Attack_Process_Name );
 rc = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (
   SystemInformationClass,
   SystemInformation,
   SystemInformationLength,
   ReturnLength );
 if( NT_SUCCESS( rc ) && strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
 {
  if(5 == SystemInformationClass)
  {
   struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
   struct _SYSTEM_PROCESSES *prev = NULL;
   while(curr)
   {    
    ANSI_STRING process_name;
    ANSI_STRING ANSI_Enemy_Name;
    UNICODE_STRING Enemy_Name;
    RtlUnicodeStringToAnsiString( &process_name, &(curr->ProcessName), TRUE);
    if( (255 > process_name.Length) && (0 < process_name.Length) )
    {
     if(0 == strncmp( process_name.Buffer, ProcessName, NT_PROCNAMELEN-1))
     {
 
      //DbgPrint("[Alarm] ProcessScan Detected\n");
      //DbgPrint("Called by %s\n",Attack_Process_Name);
       if(prev)
       {
        if(curr->NextEntryDelta)
        {
         prev->NextEntryDelta += curr->NextEntryDelta;
        }
        else
        {
         prev->NextEntryDelta = 0;
        }
       }
       else
       {
        if(curr->NextEntryDelta)
        {
         (char *)SystemInformation += curr->NextEntryDelta;
        }
        else
        {
         SystemInformation = NULL;
        }
       }
     }
    }
    RtlFreeAnsiString(&process_name);
    prev = curr;
    if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);
    else
    {
     curr = NULL;
    }
   }
  }
 }
 return rc;
}

NtUserQueryWindow(), NtUserBuildHwndList(), NtUserFindWindowEx(),
NtUserGetForegroundWindow() 라는 함수들은 창의 핸들과 관련이 있는 함수들입니다.
창의 핸들을 획득하는 것을 차단하기 위해 위의 함수들을 후킹하는 코드 입니다.

UINT_PTR NewNtUserQueryWindow(IN ULONG WindowHandle,IN ULONG TypeInformation)
{
    ULONG WindowHandleProcessID;
    CHAR Attack_Process_Name[PROCNAMELEN];
    CHAR Target_Process_Name[PROCNAMELEN];
    PEPROCESS Process;
    char *nameptr;

        GetProcessName(Attack_Process_Name);
 if(strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
 {
  WindowHandleProcessID = ((NTUSERQUERYWINDOW)(WINDOWSERVICEIDX(483)))(WindowHandle,0);
  if(PsLookupProcessByProcessId((HANDLE)WindowHandleProcessID,&Process) == STATUS_SUCCESS)
        {
   ObDereferenceObject(Process);
                 nameptr = (PCHAR)Process + gProcessNameOffset;
   strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
   Target_Process_Name[NT_PROCNAMELEN] = 0;
   if(!strncmp(Target_Process_Name,ProcessName,NT_PROCNAMELEN-1) || WindowHandleProcessID == SaruenProcessID)
   {
    return 0;
   }
  }
    }  
 return OldNtUserQueryWindow(WindowHandle,TypeInformation);
}

NTSTATUS NewNtUserBuildHwndList(IN HDESK hdesk, IN HWND hwndNext, IN ULONG fEnumChildren, IN DWORD idThread, IN UINT cHwndMax, OUT HWND *phwndFirst, OUT ULONG* pcHwndNeeded)
{
 NTSTATUS result;
    CHAR Attack_Process_Name[PROCNAMELEN];
 CHAR Target_Process_Name[PROCNAMELEN];
 ULONG ProcessID;
 PEPROCESS Process;
 char *nameptr;
 ULONG i = 0,j;
 
    GetProcessName(Attack_Process_Name);
 if(strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
 {
  if(fEnumChildren == 1)
  {
   ProcessID = OldNtUserQueryWindow((ULONG)hwndNext,0);
   if(PsLookupProcessByProcessId((HANDLE)ProcessID,&Process) == STATUS_SUCCESS)
            {
    ObDereferenceObject(Process);
                   nameptr = (PCHAR)Process + gProcessNameOffset;
     strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
    Target_Process_Name[NT_PROCNAMELEN] = 0;
    if(!strncmp(Target_Process_Name,ProcessName,NT_PROCNAMELEN-1) || ProcessID == SaruenProcessID)
    {
     return STATUS_UNSUCCESSFUL;
    }
   }
          }
  result=((NTUSERBUILDHWNDLIST)(WINDOWSERVICEIDX(312)))(hdesk,hwndNext,fEnumChildren,idThread,cHwndMax,phwndFirst,pcHwndNeeded);
  if (result == STATUS_SUCCESS)
  {
   while (i<*pcHwndNeeded)
   {
    ProcessID=OldNtUserQueryWindow((ULONG)phwndFirst[i],0);
    if(PsLookupProcessByProcessId((HANDLE)ProcessID,&Process) == STATUS_SUCCESS)
              {
                    nameptr = (PCHAR)Process + gProcessNameOffset;
      strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
     Target_Process_Name[NT_PROCNAMELEN] = 0;
     ObDereferenceObject(Process);
     if(!strncmp(Target_Process_Name,ProcessName,NT_PROCNAMELEN))
     {
       for (j=i; j<(*pcHwndNeeded)-1; j++)    
         phwndFirst[j]=phwndFirst[j+1];
       phwndFirst[*pcHwndNeeded-1]=0;
       (*pcHwndNeeded)--;
       continue;
     }
    }
    i++;
   }
  }
  return result;
 }
 return OldNtUserBuildHwndList(hdesk,hwndNext,fEnumChildren,idThread,cHwndMax,phwndFirst,pcHwndNeeded);
}

ULONG NewNtUserFindWindowEx(IN HWND hwndParent, IN HWND hwndChild, IN PUNICODE_STRING pstrClassName OPTIONAL, IN PUNICODE_STRING pstrWindowName OPTIONAL, IN DWORD dwType)
{
 ULONG result;
 ULONG ProcessID;
        PEPROCESS Process;
        char *nameptr;
        CHAR Attack_Process_Name[PROCNAMELEN];
        CHAR Target_Process_Name[PROCNAMELEN];

        GetProcessName(Attack_Process_Name);
        if(!strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
  {
   result=OldNtUserFindWindowEx(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
   return result;
  }
  result = ((NTUSERFINDWINDOWEX)(WINDOWSERVICEIDX(378)))(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
  if(strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
        {
           ProcessID = OldNtUserQueryWindow(result,0);
           if(PsLookupProcessByProcessId((HANDLE)ProcessID,&Process) == STATUS_SUCCESS)
           {
                 nameptr = (PCHAR)Process + gProcessNameOffset;
   strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
  Target_Process_Name[NT_PROCNAMELEN] = 0;
  if(!strncmp(Target_Process_Name,ProcessName,NT_PROCNAMELEN-1) || ProcessID == SaruenProcessID)
  {
   result=0;
  }
  ObDereferenceObject(Process);
           }
           
        }
 return result;
}

ULONG NewNtUserGetForegroundWindow(VOID)
{
 ULONG result;
 ULONG ProcessID;
        PEPROCESS Process;
        char *nameptr;
        CHAR Attack_Process_Name[PROCNAMELEN];
        CHAR Target_Process_Name[PROCNAMELEN];

        GetProcessName(Attack_Process_Name);
  if(!strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
  {
   result=OldNtUserGetForegroundWindow();
   return result;
  }
  result = ((NTUSERGETFOREGROUNDWINDOW)(WINDOWSERVICEIDX(404)))();
        if(strncmp(Attack_Process_Name,ProcessName,NT_PROCNAMELEN-1))
        {
           ProcessID = OldNtUserQueryWindow(result,0);
           if(PsLookupProcessByProcessId((HANDLE)ProcessID,&Process) == STATUS_SUCCESS)
           {
                 nameptr = (PCHAR)Process + gProcessNameOffset;
   strncpy(Target_Process_Name, nameptr, NT_PROCNAMELEN);
  Target_Process_Name[NT_PROCNAMELEN] = 0;
  if(!strncmp(Target_Process_Name,ProcessName,NT_PROCNAMELEN-1) || ProcessID == SaruenProcessID)
  {
   result=LastForegroundWindow;
  }
  else
  {
   LastForegroundWindow=result;
  }
  ObDereferenceObject(Process);
           }
           
        }
 return result;
}

두번쨰로 사용할 수 있는게 DKOM입니다. DKOM은 예외경우가 많이 발생할 수 있음으로,
필드 프로그램에서 사용할 떄에는, 신중에 신중을 고려하여야 할 부분입니다.

첫번째로 가장 많이 알려진 DKOM적 방법인 EPROCESS LINK를 끊는 방법입니다.
먼저 숨기고자 하는 프로세스 이름으로 EPROCESS를 찾는 함수 입니다.

PEPROCESS
FindProcessByName(char *Name)
{
 PLIST_ENTRY start_plist,plist_hTable = NULL;
 ULONG *d_pid;
 PEPROCESS eproc;
 char *nameptr;
 CHAR Process_Name[NT_PROCNAMELEN];
 NTSTATUS rc;
 plist_hTable = (PLIST_ENTRY)((*(ULONG*)
  ((ULONG)PsInitialSystemProcess + 0xC4)) + 0x1C);
 
 start_plist = plist_hTable;

 do
 {
  d_pid = (ULONG*)(((ULONG)plist_hTable + 0x8)
      - 0x1C);
  rc = PsLookupProcessByProcessId((HANDLE)*d_pid,&eproc);
  if(eproc && NT_SUCCESS(rc))
  {
   nameptr = (PCHAR)eproc + gProcessNameOffset;
   strncpy(Process_Name, nameptr, NT_PROCNAMELEN);
   Process_Name[NT_PROCNAMELEN] = 0;
   ObDereferenceObject(eproc);
   if(!strncmp(Process_Name,Name,NT_PROCNAMELEN-1))
   {
    return eproc;
   }
  }
 // DbgPrint("%s\n",Process_Name);
  plist_hTable = plist_hTable->Flink;  
 }while(start_plist != plist_hTable);
 return 0;
}

그후에는 다음과 같은 코드로 숨킬 수 있습니다.

PEPROCESS MyProcess;
PLIST_ENTRY plist_active_procs;

MyProcess = FindProcessByName(ProcessName);

    if(MyProcess)
    {
     plist_active_procs = (LIST_ENTRY *)((DWORD)MyProcess + 0x88);
     *((DWORD *)plist_active_procs->Blink) = (DWORD)plist_active_procs->Flink;
     *((DWORD *)plist_active_procs->Flink+1) = (DWORD)plist_active_procs->Blink;
     plist_active_procs->Flink = (LIST_ENTRY *) &(plist_active_procs->Flink);
     plist_active_procs->Blink = (LIST_ENTRY *) &(plist_active_procs->Flink);
    }

위의 코드에 다음과 같은 한줄을 붙여넣음으로서, 보호하고자 하는 프로세스의
PID를 0으로 만들어 접근이 불가능하게 할 수도 있습니다.

*((DWORD*)((DWORD)MyProcess+0x84)) = 0;

csrss.exe 에서 핸들을 지우는 코드 입니다.

 PEPROCESS gpeproc_csrss;

  gpeproc_csrss = (PEPROCESS)FindProcessByName("csrss.exe");
    if(!gpeproc_csrss) gpeproc_csrss = (PEPROCESS)FindProcessByName
                                                                               ("CSRSS.EXE");


if(gpeproc_csrss) EraseHandle((PEPROCESS)gpeproc_csrss, (PVOID)MyProcess);

void EraseHandle(PEPROCESS eproc, PVOID tarHandle)
{
 PTABLE_ENTRY   orig_tableEntry, p_tableEntry, *pp_tableEntry, **ppp_tableEntry;
 int a, b, c;
 int i_numHandles, i_hperPage, i_numTables;
 int i_handle;
 //DbgPrint("Hiding %x from %s process handle table.\n", tarHandle, (DWORD)eproc+gul_ProcessNameOffset);
 i_numHandles = *(int*)((*(PDWORD)((DWORD) eproc + 0xC4)) + 0x3C);
 orig_tableEntry = (PTABLE_ENTRY)*(PDWORD)((*(PDWORD)((DWORD) eproc + 0xC4)));
 i_numTables = ((DWORD)orig_tableEntry & 3);
 i_hperPage = PAGE_SIZE/sizeof(TABLE_ENTRY);
 
 if (i_numTables == 0)
 {
  //DbgPrint("Found a single level handle table.\n");
  p_tableEntry = (PTABLE_ENTRY)((DWORD)orig_tableEntry & 0xfffffff8);
  for (a = 0; a < i_hperPage; a++)
  {
   if (((p_tableEntry[a].object ^ 0x80000000) & 0xfffffff8) == ((DWORD)tarHandle - 0x18))
   {
    //DbgPrint("Handle = %x Object Header %x Security %x\n", a*4, ((p_tableEntry[a].object | 0x80000000) & 0xfffffff8), p_tableEntry[a].security);
    p_tableEntry[a].object = 0;
    p_tableEntry[a].security = 0;
   }
  }
 }
 else if (i_numTables == 1)
 {
  //DbgPrint("Found a two level handle table.\n");
  pp_tableEntry = (PPTABLE_ENTRY)((DWORD)orig_tableEntry & 0xfffffff8);
  for (a = 0; a < i_hperPage; a++)
  {
   if (pp_tableEntry[a] == NULL)
    break;
   for (b = 0; b < i_hperPage; b++)
   {
    if (((pp_tableEntry[a][b].object ^ 0x80000000) & 0xfffffff8) == ((DWORD)tarHandle - 0x18))
    {
     //DbgPrint("Handle = %x Object Header %x Security %x\n", ((a*512)+b)*4, ((pp_tableEntry[a][b].object | 0x80000000) & 0xfffffff8), pp_tableEntry[a][b].security);
     pp_tableEntry[a][b].object = 0;
     pp_tableEntry[a][b].security = 0;
    }
   }
   
  }
 }
 else if (i_numTables == 2)
 {
  //DbgPrint("Found a three level handle table.\n");
  ppp_tableEntry = (PPPTABLE_ENTRY)((DWORD)orig_tableEntry & 0xfffffff8);
  for (a = 0; a < i_hperPage; a++)
  {
   if (ppp_tableEntry[a] == NULL)
    break;
   for (b = 0; b < i_hperPage; b++)
   {
    if (ppp_tableEntry[a][b] == NULL)
     break;
    for (c = 0; c < i_hperPage; c++)
    {
     if (((ppp_tableEntry[a][b][c].object ^ 0x80000000) & 0xfffffff8) == ((DWORD)tarHandle - 0x18))
     {
      //DbgPrint("Handle = %x Object Header %x Security %x\n", ((a*512)+(b*256)+c)*4, ((ppp_tableEntry[a][b][c].object | 0x80000000) & 0xfffffff8), ppp_tableEntry[a][b][c].security);
      ppp_tableEntry[a][b][c].object = 0;
      ppp_tableEntry[a][b][c].security = 0;
     }
    }
   
   }
  }
 }
}

PspCidTable에서 오브젝트를 지우는 함수 입니다.

먼저 다음과 같이 PspCidTable을 지우는 함수를 먼저 호출 합니다.

DWORD gcid_table;

gcid_table = GetPspCidTable();

DWORD
GetPspCidTable()
{
    PVOID pPspCidTable = NULL;
    ULONG i;
    UNICODE_STRING  usPsLookup;
    PUCHAR Buff;
   
    RtlInitUnicodeString( &usPsLookup, L"PsLookupProcessByProcessId" );
    Buff = MmGetSystemRoutineAddress( &usPsLookup );
    if( Buff != NULL )
    {   
        for( i = 0; i < 0x40; i++, Buff++ )
        {
            if( *(PUSHORT)(Buff) == 0x35ff && *((PUCHAR)Buff+6) == 0xe8 )
            {
                pPspCidTable = (PVOID)(*(PULONG)(Buff+2));
                break;
            }
        }
    }
    return (DWORD)pPspCidTable ? *(DWORD*)pPspCidTable : (DWORD)NULL;
}

 EraseObjectFromPspCidTable(gcid_table, (PVOID)MyProcess, 0,*((DWORD*)((DWORD)MyProcess+0x84)), 0 );

void EraseObjectFromPspCidTable(DWORD handle_table, PVOID tarHandle, enum ObjectType obj_type, DWORD pid, DWORD tid)
{
 PTABLE_ENTRY   orig_tableEntry, p_tableEntry, *pp_tableEntry, **ppp_tableEntry;
 int a, b, c;
 int i_numHandles, i_hperPage, i_numTables;
 int i_handle;
 i_numHandles = *(int*)(handle_table + 0x3c);
 orig_tableEntry = (PTABLE_ENTRY)*(PDWORD)(handle_table + 0);
 i_numTables = ((DWORD)orig_tableEntry & 3);
 i_hperPage = PAGE_SIZE/sizeof(TABLE_ENTRY);
 
 if (i_numTables == 0)
 {
 
//   DbgPrint("Found a single level handle table.\n");
  p_tableEntry = (PTABLE_ENTRY)((DWORD)orig_tableEntry & 0xfffffff8);
  for (a = 0; a < i_hperPage; a++)
  {
   if (((p_tableEntry[a].object | 0x80000000) & 0xfffffff8) == ((DWORD)tarHandle))
   {
//     DbgPrint("[%d]\n",a);
//     DbgPrint("Handle = %x Object %x Security %x\n", a*4, ((p_tableEntry[a].object | 0x80000000) & 0xfffffff8), p_tableEntry[a].security);
   
//     add_index(&g_PspCidTableList, SINGLE_LEVEL,obj_type,(DWORD)tarHandle,pid,tid, a,0, 0, p_tableEntry[a].object, p_tableEntry[a].security);
   
    p_tableEntry[a].object = 0;
    p_tableEntry[a].security = ((PHANDLE_TABLE)handle_table)->FirstFree;
    ((PHANDLE_TABLE)handle_table)->FirstFree = (ULONG)( (tid!=0) ? tid : pid );
   }
  }
 }
 else if (i_numTables == 1)
 {
//   DbgPrint("Found a two level handle table.\n");
  pp_tableEntry = (PPTABLE_ENTRY)((DWORD)orig_tableEntry & 0xfffffff8);
 
  for (a = 0; a < i_hperPage; a++)
  {
   if (pp_tableEntry[a] == NULL)
    break;
   for (b = 0; b < i_hperPage; b++)
   {
    //DbgPrint("Comparing %x to %x\n", ((pp_tableEntry[a][b].object | 0x80000000) & 0xfffffff8), tarHandle);
    if (((pp_tableEntry[a][b].object | 0x80000000) & 0xfffffff8) == ((DWORD)tarHandle))
    {
//      DbgPrint("[%d][%d]\n",a,b);
//      DbgPrint("Handle = %x Object %x Security %x\n", ((a*512)+b)*4, ((pp_tableEntry[a][b].object | 0x80000000) & 0xfffffff8), pp_tableEntry[a][b].security);
//      add_index(&g_PspCidTableList, DOUBLE_LEVEL,obj_type,(DWORD)tarHandle, pid,tid,  a,b, 0, pp_tableEntry[a][b].object, pp_tableEntry[a][b].security);
     pp_tableEntry[a][b].object = 0;
     pp_tableEntry[a][b].security = ((PHANDLE_TABLE)handle_table)->FirstFree;
     ((PHANDLE_TABLE)handle_table)->FirstFree = (ULONG)( (tid!=0) ? tid : pid );
    }
   }
   
  }
 }
 else if (i_numTables == 2)
 {
//   DbgPrint("Found a three level handle table.\n");
  ppp_tableEntry = (PPPTABLE_ENTRY)((DWORD)orig_tableEntry & 0xfffffff8);
  for (a = 0; a < i_hperPage; a++)
  {
   if (ppp_tableEntry[a] == NULL)
    break;
   for (b = 0; b < i_hperPage; b++)
   {
    if (ppp_tableEntry[a][b] == NULL)
     break;
    for (c = 0; c < i_hperPage; c++)
    {
     if (((ppp_tableEntry[a][b][c].object | 0x80000000) & 0xfffffff8) == ((DWORD)tarHandle))
     {
//       DbgPrint("Handle = %x Object %x Security %x\n", ((a*512)+(b*256)+c)*4, ((ppp_tableEntry[a][b][c].object | 0x80000000) & 0xfffffff8), ppp_tableEntry[a][b][c].security);
//       add_index(&g_PspCidTableList, TRIPLE_LEVEL,obj_type, (DWORD)tarHandle, pid,tid,  a,b, c, ppp_tableEntry[a][b][c].object, ppp_tableEntry[a][b][c].security);
      ppp_tableEntry[a][b][c].object = 0;
      ppp_tableEntry[a][b][c].security = ((PHANDLE_TABLE)handle_table)->FirstFree;
      ((PHANDLE_TABLE)handle_table)->FirstFree = (ULONG)( (tid!=0) ? tid : pid );
     }
    }
   
   }
  }
 }
}

HandleListEntry 해제하는 코드 입니다.

UnHookHandleListEntry((PEPROCESS)MyProcess);

void UnHookHandleListEntry(PEPROCESS eproc)
{
 PLIST_ENTRY plist_hTable = NULL;
 plist_hTable = (PLIST_ENTRY)((*(PDWORD)((DWORD) eproc + 0xc4)) +  0x1c);
 //DbgPrint("Unhooking the handle table of Process: %s\n", (DWORD)eproc+gul_ProcessNameOffset);
 *((DWORD *)plist_hTable->Blink) = (DWORD) plist_hTable->Flink;
 *((DWORD *)plist_hTable->Flink+1) = (DWORD) plist_hTable->Blink;
 //plist_hTable->Flink = (LIST_ENTRY *) &(plist_hTable->Flink); // Change the current LIST_ENTRY
 //plist_hTable->Blink = (LIST_ENTRY *) &(plist_hTable->Flink); // so we don't point to crap
}

프로세스에 속해 있는 스레드를 숨기는 코드 입니다.

if(gpeproc_csrss) HideThreadsInTargetProcess((PEPROCESS)MyProcess, gpeproc_csrss);


void HideThreadsInTargetProcess(PEPROCESS eproc, PEPROCESS target_eproc)
{
 PETHREAD start, walk;
 DWORD check1, check2;
 if (eproc == NULL)
  return;
 check1 = *(DWORD *)((DWORD)eproc + 0x50);
 check2 = ((DWORD)eproc + 0x50);
 // If check1 points back to the EPROCESS, there are no threads in the process.
 // It must be exiting.
 if (check1 == check2)
  return;
 start = *(PETHREAD *)((DWORD)eproc + 0x50);
 start = (PETHREAD)((DWORD)start - 0x1b0);
 walk = start;
 do
 {
  EraseHandle(target_eproc, walk);
  walk = *(PETHREAD *)((DWORD)walk + 0x1b0);
  walk = (PETHREAD)((DWORD)walk - 0x1b0);
 }while (walk != start);
}

 


지금 소개한 프로세스 숨기는 코드들만 사용하여도, 충분히 강력한 효과를 내실 수 있
을 것입니다. 하지만 꼭 명심하시기 바랍니다. DKOM을 사용할떄는 충분한 필드 테스트가
선행되어져야 한다는 것을...

여담이지만, 사실 이 글의 제목은 'Anti Game hacking 프로그램이 갖추어야할 기능들과
약점들.' 이었는데요. 글을 쓰다보니 -_-;; 필요한 기능과 코드만 다루어도 글의 길이가
꾀 길더군요. 그래서 두편으로 나누기로 결정을 하였습니다. 그럼 다음편에서는
Anti GH 프로그램의 약점과 그 대안에 대해서 알아보도록 하겠습니다.
이 글에서 잘못된 부분은 dual@null2root.org 로 알려주시거나, 이 글에 리플을 달아
주셔도 감사하겠습니다. 그럼 이만 (__)...

프로세스에서 메모리 패턴 검사 :

윈도우,클레스 목록에서 검사 :

이벤트,뮤텍스,파일맵 이름 검사 :

CRC 검사 :

참고 문헌 (?)
- 추후 추가 예정.
이올린에 북마크하기(0) 이올린에 추천하기(0)

Posted by Dual

2007/12/02 12:58 2007/12/02 12:58
Response
208 Trackbacks , a comment
RSS :
http://dual5651.hacktizen.com/tc/rss/response/312

Trackback URL : http://dual5651.hacktizen.com/tc/trackback/312

Trackbacks List

  1. File CRC Check 검사기법 우회하기 - Target : GomEncoder

    Tracked from #44u61l5f 2009/02/10 16:16 Delete

    Long time no see!Dual입니다. :0아주 오~~랜만에 활동시작 겸 RE에 관한 글을 써보고자 합니다.주제는? File CRC Check 검사 우회하기(?) 입니다.대상은 GomEncoder로 잡았는데요, 별 다른 이유가 있는 것은 아닙니다.그런데 GomEnc가 CRC 체크를 하는 이유는 모르겠습니다(바이러스에 의한 손상검사?)아시는 분은 댓글 좀 알려주세요. ;0먼저 한번 생각해 보죠.저번에 간단히 프로세스의 CRC체크를 우회(?)하...

  2. test2

    Tracked from test2 2009/02/11 11:30 Delete

    test2

  3. pimhwwgb

    Tracked from pimhwwgb 2009/03/07 07:16 Delete

    pimhwwgb

  4. anti aging creams

    Tracked from anti aging creams 2009/06/29 12:32 Delete

    dead fee show primary your breath thus method aye: krigopezp at skin status advise specific information existing percent.

  5. mico bikini

    Tracked from mico bikini 2009/07/28 03:58 Delete

    natalia tena nude <a href="http://sexmoviesfree74.5gighost.com/natalia-tena-nude.html">natalia tena nude</a>

  6. zeps bbs

    Tracked from zeps bbs 2009/07/29 15:33 Delete

    tawas phone system <a href="http://maifunemae.wordpress.com/">tawas phone system</a>

  7. zero turn mowers

    Tracked from zero turn mowers 2009/07/29 16:23 Delete

    tawas business analysis <a href="http://vatzefak.wordpress.com/">tawas business analysis</a>

  8. Margot Kidder Nude

    Tracked from Margot Kidder Nude 2009/08/18 01:53 Delete

    Margot Kidder Nude <a href="http://www.kaboodle.com/margot_kidder_nude_52">Margot Kidder Nude</a> Photos and Video. jgr1uig98d

  9. johns ameteurs

    Tracked from johns ameteurs 2009/08/19 20:32 Delete

    asian fittness <a href="http://www.kaboodle.com/asian_fittness_63">asian fittness </a> vintage apron patterns <a href="http://www.kaboodle.com/vintage_apron_patterns_87">vintage apron patterns </a>

  10. shemale route

    Tracked from shemale route 2009/08/27 16:50 Delete

    castro supreme xxx <a href="http://www.kaboodle.com/castro_supreme_xxx_42">castro supreme xxx </a>

  11. Hydrocodone online without prescription.

    Tracked from Purchase hydrocodone online. 2009/09/06 11:33 Delete

    Hydrocodone online. Search hydrocodone online without a prescription. Easy way to buy hydrocodone online. Buying hydrocodone online. Online hydrocodone. Buy hydrocodone online discount cheap pharmacy. Purchase hydrocodone online. Hydrocodone and online...

  12. Buy hydrocodone online.

    Tracked from Buy hydrocodone online. 2009/09/06 13:57 Delete

    Easy way to buy hydrocodone online. Buy hydrocodone online. Buy hydrocodone online without prescription. Buy hydrocodone online without a prescription.

  13. Buy tramadol at a cheap price online.

    Tracked from Buy tramadol. 2009/09/07 15:34 Delete

    Buy tramadol online cod. Buy tramadol. Tramadol great buy.

  14. Cheap phentermine cod.

    Tracked from Cheap phentermine. 2009/09/07 21:38 Delete

    Cheap phentermine diet pill. Phentermine cheap. Buy phentermine cheap.

  15. Phentermine diet pills effects of diet pills home.

    Tracked from Phentermine diet pills buy phentermine diet pill. 2009/09/08 00:14 Delete

    Phentermine diet pills. Phentermine diet pills effects of diet pills home. Phentermine diet pills without pecription. Phentermine diet pills diet pills.

  16. Side effects of drug xanax.

    Tracked from Xanax side effects. 2009/09/08 17:38 Delete

    Side effects of drug xanax. Xanax ingredients side effects. Side effects of xanax.

  17. Oxycontin cost.

    Tracked from Oxycontin addiction symptoms. 2009/09/09 01:53 Delete

    Hartford oxycontin attorneys. Oxycontin. Freebasing oxycontin.

  18. Vicodin.

    Tracked from Vicodin withdrawal. 2009/09/09 10:34 Delete

    Vicodin.

  19. Where to buy oxycontin.

    Tracked from Buy oxycontin. 2009/09/09 19:06 Delete

    Buy oxycontin. Buy oxycontin online. Buy cheap oxycontin.

  20. Georgia oxycontin lawyers.

    Tracked from Oxycontin. 2009/09/10 14:23 Delete

    Hartford oxycontin attorneys. Oxycontin. Oxycontin pdr. Oxycontin las vegas. Oxycontin purdue legal news. Addiction to oxycontin.

  21. Buy tramadol amex.

    Tracked from Buy tramadol in the united states. 2009/09/15 01:32 Delete

    Buy tramadol index. Buy tramadol.

  22. Tramadol.

    Tracked from Tramadol cod. 2009/09/16 06:24 Delete

    Tramadol cod. Taking tramadol while pregnant. Tramadol.

  23. Adderall xr.

    Tracked from Adderall xr. 2009/09/16 17:33 Delete

    Adderall xr.

  24. Buying oxycontin online.

    Tracked from California buy oxycontin must mail prescription. 2009/09/18 19:23 Delete

    Buy oxycontin. Buy oxycodone oxycontin without a perscription. Buy online percocet oxycontin. Buy oxycontin without a presription. Buying oxycontin.

  25. Buy hydrocodone online.

    Tracked from Order hydrocodone online. 2009/09/26 22:02 Delete

    Online pharmacies hydrocodone. Hydrocodone and online consultation. Buy online hydrocodone codeine hydrocodone. Buy hydrocodone online.

  26. Buy tramadol online cod.

    Tracked from Tramadol buy. 2009/09/27 14:51 Delete

    Buy tramadol online cod. Buy super cheap phentermine and tramadol. Buy tramadol pharmacy index. Buy tramadol. Buy cheap tramadol mg tablets only in us online.

  27. Hydrocodone how to administer safely.

    Tracked from Hydrocodone online. 2009/09/28 10:35 Delete

    Hydrocodone withdrawl. Hydrocodone. Pregnant and taking hydrocodone. Hydrocodone prescription.

  28. Xanax.

    Tracked from Generic xanax 2 mg no prescription. 2009/09/29 12:20 Delete

    Buy generic xanax information. Titel auteur datum xanax medication bmnwbbuk. Xanax. Xanax 180 pills.

  29. Online pharmacy oxycontin.

    Tracked from Online pharmacy oxycontin. 2009/09/30 18:41 Delete

    Online pharmacy oxycontin.

  30. tsc tractor supply

    Tracked from tsc tractor supply 2009/10/01 05:17 Delete

    cibolo texas land for sale <a href="http://cibolo-texas-land-for-sale.gscoiqrqnvq.com/">cibolo texas land for sale</a> antonym worksheets <a href="http://antonym-worksheets.gscoiqrqnvq.com/">antonym worksheets</a>

  31. Buy xanax online.

    Tracked from Buy xanax online. 2009/10/01 14:19 Delete

    Buy xanax online without a prescription. Buy xanax overnight with online consultation. Buy xanax online.

  32. Buy xanax.

    Tracked from Buy cheap xanax. 2009/10/02 04:10 Delete

    Buy xanax. Xanax. Buy xanax online. Fda approved xanax us licensed doctors.

  33. Valium liquid form.

    Tracked from Valium liquid form. 2009/10/06 00:32 Delete

    Valium liquid form.

  34. Buy ultram cheapest site.

    Tracked from Buy ultram. 2009/10/06 23:05 Delete

    Canada pharmacy buy online ultram. Buy ultram from discount store. Buy ultram cheapest site. Ultram buy ultram online order cheap ultram. Buy ultram.

  35. Amoxicillin.

    Tracked from Amoxicillin rx655. 2009/10/07 10:57 Delete

    Amoxicillin for acne. Amoxicillin dosage. Amoxicillin online homepage. Amoxicillin. Prescription free amoxicillin. Taking amoxicillin while pregnant. Amoxicillin trihydrate. Amoxicillin anti inflammatory. Amoxicillin lowest.

  36. Ultram addiction.

    Tracked from Ultram withdrawal ultram addiction. 2009/10/07 23:58 Delete

    Ultram addiction.

  37. Prescription free amoxicillin.

    Tracked from Prescription free amoxicillin. 2009/10/08 16:48 Delete

    Prescription free amoxicillin.

  38. Order fioricet.

    Tracked from Generic fioricet. 2009/10/09 01:11 Delete

    Fioricet. Cheapest fioricet. Order fioricet. Cheap fioricet. Fioricet 2bwithout 2bprescription 2bsi. Fioricet usage and indications.

  39. Cheap codeine no prescription.

    Tracked from Cheap codeine no prescription. 2009/11/07 02:14 Delete

    Cheap codeine no prescription.

  40. Generic oxycontin photo.

    Tracked from Buy oxycontin. 2009/11/14 09:42 Delete

    Oxycontin online. Oxycontin. Oxycontin crush. Oxycontin mg 210. Oxycontin pills.

  41. Xanax no prescription.

    Tracked from Xanax. 2009/11/15 07:48 Delete

    Buy xanax online. Xanax.

  42. Buy phentermine.

    Tracked from Phentermine 37.5. 2009/11/15 17:00 Delete

    Phentermine. Phentermine success story. Phentermine hcl.

  43. Adderall.

    Tracked from Adderall xr adverse effects. 2009/11/16 08:54 Delete

    Adderall. Adderall treatment for bulimia.

  44. Buy xanax online.

    Tracked from No prescription needed purchasing xanax. 2009/11/16 23:07 Delete

    Xanax dosage. Buy xanax. No rx online xanax. Xanax. Xanax effect. Xanax without prescription. Xanax 2mg.

  45. Lorazepam side effects.

    Tracked from Buy lorazepam. 2009/11/17 08:13 Delete

    Lorazepam. Cheap lorazepam discount pharmacy.

  46. Lortab.

    Tracked from Lortab online. 2009/11/18 00:24 Delete

    Lortab withdrawal. Lortab. How long does lortab effects last. Lortab addiction. Lortab online pharmacy. Lortab overnight.

  47. What does a lortab 10 look like.

    Tracked from Buy lortab with no medical records. 2009/11/18 00:38 Delete

    Lortab no prescription. Lortab. Lortab 10 500. Snorting lortab. How to snort lortab.

  48. Lorazepam hydrocodone federal express.

    Tracked from Lorazepam. 2009/11/18 16:11 Delete

    Conversion table lorazepam to valium. Lorazepam order prescription online. Lorazepam side effects. Lorazepam order online consultation. Lorazepam plo gel. Diazepam to lorazepam conversion.

  49. Patient information on viagra sildenafil citrate.

    Tracked from Buy sildenafil citrate. 2009/11/19 00:47 Delete

    Sildenafil. Patient information on viagra sildenafil citrate.

  50. Lorazepam 0.5mg.

    Tracked from Lorazepam lorazapam cod. 2009/11/19 09:44 Delete

    Longterm consequences of lorazepam use. Ic lorazepam buspar.

  51. Codeine.

    Tracked from Codeine online. 2009/11/20 00:24 Delete

    Sell codeine. Apap codeine. Codeine combined pseudoephedrine. Robitusin with codeine. How codeine effects the brain. Liquid codeine how to make. Codeine.

  52. Lorazepam.

    Tracked from Lethal dose of lorazepam. 2009/11/20 12:19 Delete

    Lorazepam. Ativan lorazepam information.

  53. Adderall.

    Tracked from Buy adderall. 2009/11/21 07:31 Delete

    Buy adderall without a prescription. Ordering adderall.

  54. Ambien online.

    Tracked from Online meds no prescription ambien. 2009/11/22 04:19 Delete

    Buy ambien online no prescription. Ambien cr buy online no prescription. Buy ambien online cod.

  55. Tramadol.

    Tracked from Tramadol. 2009/11/22 16:19 Delete

    Tramadol side effects. Tramadol. Tramadol cheap no rx free overnight shipping.

  56. Celexa.

    Tracked from Celexa. 2009/11/23 03:42 Delete

    Celexa and pregnancy. Celexa. Celexa pregnancy.

  57. How while on adderall xr.

    Tracked from Adderall xr. 2009/11/23 21:04 Delete

    Adderall xr side effects. Adderall xr. Pharmacy price for adderall xr 20mg 30 capsules.

  58. Ritalin- side effects.

    Tracked from Experiments with ritalin. 2009/11/24 03:44 Delete

    What is ritalin used for. Ritalin picture. History of ritalin. Ritalin. Scientific evidence pro con ritalin. Ritalin- side effects.

  59. database empire last

    Tracked from database empire 2009/11/30 10:53 Delete

    [...] A second mortar attack 15 minutes later missed the police station in Stewartstown, about 10 miles away, but damaged a primary school and houses. Nevertheless,either In the most recent quarter, the company strengthened its reserves by about $38 mi...

  60. Tramadol.

    Tracked from Tramadol. 2010/01/03 11:10 Delete

    Tramadol side effects. Buy cheap tramadol mg tablets only in us online. Tramadol. Tramadol dog.

  61. What is valtrex.

    Tracked from Generic valtrex. 2010/01/03 12:19 Delete

    Valtrex.

  62. Klonopin.

    Tracked from Klonopin. 2010/01/04 00:09 Delete

    Fedex klonopin with precription. Klonopin side effects. Klonopin.

  63. Valtrex.

    Tracked from Buy valtrex online. 2010/01/04 17:37 Delete

    Valtrex. Dosage for valtrex. Buy valtrex without prescription. Dosage for valtrex oral.

  64. Ultram addiction.

    Tracked from Ultram dosage. 2010/01/05 04:26 Delete

    Ultram er. Buy ultram cheapest site. Ultram addiction.

  65. Valtrex.

    Tracked from When does valtrex go generic. 2010/01/05 16:00 Delete

    Buy valtrex com. Valtrex.

  66. Ambien overnight.

    Tracked from Ambien. 2010/01/06 03:09 Delete

    Ambien cr. Does ambien interrupt the menstrual cycle. Ambien side affects. Ambien. Employment drug test ambien.

  67. Klonopin.

    Tracked from Klonopin. 2010/01/06 14:28 Delete

    Klonopin side effects. Buy klonopin online. Klonopin. Can i shoot up klonopin. Klonopin erectile dysfunction.

  68. Tramadol.

    Tracked from Tramadol. 2010/01/07 13:24 Delete

    White tramadol with 377 on the side.

  69. Valtrex and achne.

    Tracked from Valtrex. 2010/01/07 22:55 Delete

    Valtrex. Valtrex als.

  70. Ultram addiction.

    Tracked from Ultram information from drugs com. 2010/01/08 11:07 Delete

    Ultram. Ultram warnings.

  71. Valtrex.

    Tracked from B valtrex. 2010/01/08 22:58 Delete

    Valtrex. Valtrex prices. Buy valtrex online. Valtrex medication.

  72. Ultram.

    Tracked from Ultram. 2010/01/09 14:06 Delete

    Ultram er. Difference between ultram and tramadol. Ultram information. Is ultram addictive. Ultram.

  73. Ativan.

    Tracked from Lorazepam ativan information and resources. 2010/01/10 02:13 Delete

    Ativan.

  74. Ambien sex.

    Tracked from Ambien. 2010/01/10 18:52 Delete

    Ambien. Ambien cr addiction. Generic ambien. Ambien cr.

  75. Klonopin.

    Tracked from Xanax with klonopin. 2010/01/11 22:06 Delete

    Klonopin under eye. Affects of klonopin addiction. Klonopin withdrawal symptoms. Klonopin. Order klonopin without prescription.

  76. Can you inject klonopin wafer.

    Tracked from Klonopin. 2010/01/12 19:12 Delete

    Klonopin withdrawal. Klonopin and alcoholics. Is librium comparable to klonopin. Klonopin. Klonopin lethal dose.

  77. Ambien addiction.

    Tracked from Generic ambien. 2010/01/14 00:55 Delete

    Ambien next day delivery us. Ambien. Where can i buy ambien for next day delivery. Buy ambien online cod. Ambien cr and weight loss. Addiction to ambien. Ambien no prescription needed. Ambien cr. Ambien next day delivery where.

  78. Ativan.

    Tracked from Generic ativan. 2010/01/14 16:15 Delete

    Ativan. Ativan treatmenr for seizures. Order ativan fast local delivery wholesale price. Medicine ativan.

  79. Jack black well you re not hardcore unless.

    Tracked from Jack black. 2010/01/15 04:52 Delete

    Black jack mountain oklahoma. Sedona pottery artist jack black. Jack black. Jack black lyrics.

  80. Ativan plo.

    Tracked from Ativan. 2010/01/15 11:47 Delete

    Ativan a narcotic. Www.weird skin sensations from rx ativan. Ativan. Rme ativan. Buy ativan online from discount pharmacy store.

  81. Klonopin lynx discussion board.

    Tracked from Klonopin ocd. 2010/01/15 23:57 Delete

    Klonopin side effects. Klonopin social anxiety. Klonopin.

  82. Ambien cr.

    Tracked from Ambien sleeping pill. 2010/01/16 11:06 Delete

    Long term ambien. Ambien sleeping pill. Ambien online. Ambien overnight. Ambien. Ambien addiction. Buy ambien.

  83. Tramadol.

    Tracked from Tramadol. 2010/01/16 21:23 Delete

    Comparative potencies of opioids tramadol. Tramadol.

  84. Valtrex.

    Tracked from Valtrex. 2010/01/17 14:43 Delete

    Valtrex.

  85. Ultram withdrawal.

    Tracked from Ultram. 2010/01/17 23:42 Delete

    Ultram.

  86. Ambien cr color.

    Tracked from Ambien purchase omline. 2010/01/19 23:27 Delete

    Ambien cr. Ambien online. Ambien. Where can i buy ambien for next day delivery. Ambien dosage.

  87. Ultram.

    Tracked from Ultram er. 2010/01/22 06:18 Delete

    Ultram. Ultram addiction.

  88. Valtrex side effects.

    Tracked from Valtrex and acne. 2010/01/22 23:04 Delete

    Valtrex and achn e. Side effects for valtrex. Valtrex. Valtrex side effects. Valtrex and flu shot.

  89. Ultram.

    Tracked from Buy ultram cheapest site. 2010/01/24 00:41 Delete

    Buy ultram pharmacy online. Ultram withdrawal. Ultram medicine ultram. Ultram addiction.

  90. Tramadol.

    Tracked from Tramadol hydrochloride. 2010/01/24 18:19 Delete

    Cod overnight tramadol. Tramadol saturday delivery. Tramadol. How much tramadol for daily use for dogs.

  91. Ultram fed ex.

    Tracked from Tramadol ultram medicine. 2010/01/25 04:17 Delete

    Ultram buy cheap no prescription.

  92. Ambien.

    Tracked from Ambien online no prescription overnight delivery. 2010/01/25 16:38 Delete

    Ambien overdose. Ambien. Generic ambien. Ambien hallucinations dizziness.

  93. Ultram.

    Tracked from Ultram er tablets. 2010/01/26 00:53 Delete

    Buy ultram cheapest site.

  94. Valtrex.

    Tracked from Valtrex. 2010/01/26 16:20 Delete

    Valtrex. Valtrex and flu shot. Buy valtrex without prescription. Buy valtrex online.

  95. Ambien cr.

    Tracked from Ambien. 2010/01/27 09:35 Delete

    Ambien us pharmacy. Ambien cr. Ambien. Where can i buy ambien for next day delivery.

  96. Ambien cr.

    Tracked from Ambien. 2010/01/27 15:56 Delete

    Ambien rx. Ambien.

  97. Ativan -buy -buying -online -cheap.

    Tracked from Ativan drug information. 2010/01/28 01:20 Delete

    Ativan. Ativan nursing info. Ativan use in seizure treatment. Buy ativan online from discount pharmacy store.

  98. Valtrex.

    Tracked from Valtrex. 2010/01/28 11:44 Delete

    Valtrex.

  99. Side effects of valtrex.

    Tracked from Valtrex. 2010/01/28 20:32 Delete

    Valtrex and achn e. Valtrex. Valtrex and flu shot. Valtrex and achne. Generic valtrex.

  100. Klonopin.

    Tracked from Klonopin ratings. 2010/01/29 11:40 Delete

    Klonopin side effects. Buy klonopin. Xanax or klonopin. Klonopin online. Klonopin. Klonopin sr prescribing information. Snorting klonopin.

  101. Ultram.

    Tracked from Ultram. 2010/01/29 20:57 Delete

    Ultram withdrawal symptoms. Ultram er.

  102. Ativan pregnancy.

    Tracked from Ativan dosage. 2010/01/30 11:34 Delete

    Ativan. Ativan treatmenr for seizures. Ativan lorazepam.

  103. Ambien cr 12.5 photo.

    Tracked from Ambien. 2010/01/30 21:25 Delete

    Ambien tolerance. Ambien cr and weight loss. Ambien. Ambien addiction.

  104. Klonopin side effects.

    Tracked from Is librium comparable to klonopin. 2010/01/31 11:34 Delete

    Klonopin.

  105. Ativan.

    Tracked from Ativan. 2010/01/31 21:21 Delete

    Prescription drugs ativan depakote. Ativan potentiates. Ativan without prescription. Ativan. Ativan online prescription overnight mastercard. Ativan medicine.

  106. Pharmacy order generic xanax.

    Tracked from How long does xanax stay in your system. 2010/02/01 07:34 Delete

    Xanax dosage. Xanax. Xanax during pregnancy.

  107. Buy klonopin no prescription.

    Tracked from Klonopin drug dosage. 2010/02/02 07:58 Delete

    Valium vs klonopin.

  108. Valtrex.

    Tracked from Side effects for valtrex. 2010/02/02 20:05 Delete

    Valtrex. Generic valtrex.

  109. Klonopin.

    Tracked from Klonopin. 2010/02/03 05:05 Delete

    Klonopin anxiety dose. Klonopin abuse. Buy klonopin online. Klonopin. Klonopin withdrawl symptoms.

  110. Dosage for valtrex.

    Tracked from Valtrex. 2010/02/03 19:17 Delete

    Valtrex.

  111. Ambien next day delivery canada.

    Tracked from Ambien. 2010/02/04 05:53 Delete

    Ambien latest side effects. Ambien. Long term ambien. Ambien side effects.

  112. Buy cialis buy viagara.

    Tracked from Cialis. 2010/02/04 16:47 Delete

    Cialis.

  113. Buy ativan.

    Tracked from Ativan. 2010/02/04 20:16 Delete

    Ativan. Ativan pregnancy. Ativan caffeine interaction. What is the half life of ativan sl. Can you give ativan to a dog.

  114. Hydrocodone cause mental side effects.

    Tracked from Side effects of hydrocodone. 2010/02/04 20:30 Delete

    Hydrocodone and side effects. Alcohol hydrocodone side effects.

  115. Ultram.

    Tracked from Ultram er. 2010/02/05 05:57 Delete

    Ultram withdrawal. Ultram. Ultram prescriptio.

  116. Augmentin xr dosage.

    Tracked from Antibiotic augmentin side effects. 2010/02/05 10:51 Delete

    Augmentin. Augmentin used for. Augmentin per ml. Augmentin 875. Augmentin allergic reactions symptoms.

  117. Valtrex.

    Tracked from Valtrex. 2010/02/05 19:04 Delete

    Valtrex. Valtrex use during pregnancy.

  118. Percocet.

    Tracked from Buy percocet online without office visit. 2010/02/05 23:00 Delete

    Percocet without prescription. Cheap percocet. Buy percocet. Percocet. Generic percocet. Gereric names for percocet 5 325.

  119. Klonopin overnight without a prescription.

    Tracked from Klonopin. 2010/02/06 08:26 Delete

    Klonopin addiction. Buy klonopin online. Klonopin sr prescribing information. Klonopin survivors. Klonopin. Online klonopin fed exed over night. Klonopin online next day delivery usa.

  120. Ultram tramadol.

    Tracked from Tramadol. 2010/02/06 17:18 Delete

    Tramadol overdose. Tramadol hcl. Tramadol.

  121. Tramadol.

    Tracked from Tramadol. 2010/02/06 18:29 Delete

    Canine tramadol. Tramadol cod. Tramadol. Tramadol medication. Tramadol 180 electronic check.

  122. Tramadol.

    Tracked from Cheap tramadol cheap tramadol cheap tramadol. 2010/02/06 22:21 Delete

    Comparative potencies of opioids tramadol. Buy tramadol online save wholesale price yep. Tramadol side effects. Tramadol affects drug test. Tramadol. Tramadol 50mg. Tramadol maintence.

  123. Ativan.

    Tracked from Ativan. 2010/02/07 03:15 Delete

    Ativan. Rme ativan. Generic ativan. Ativan treatmenr for seizures.

  124. Ambien.

    Tracked from Ambien. 2010/02/07 09:55 Delete

    Ambien. Generic ambien. Ambien prescriptions. Ambien side effects. Drugs detected on drug test ambien.

  125. Ambien addiction.

    Tracked from Suicide ambien. 2010/02/07 11:37 Delete

    Ambien.

  126. Lorazepam y 57.

    Tracked from Lorazepam. 2010/02/07 15:10 Delete

    Lorazepam. Lorazepam ativan information and resources. Ativan lorazepam information. Lorazepam to valium conversion. Ativan lorazepam.

  127. How to extract acitaminiaphine from percocet.

    Tracked from Percocet. 2010/02/08 02:23 Delete

    Compare and contrast percocet and oxycodone apap. Percocet.

  128. Zolpidem.

    Tracked from Cheap zolpidem. 2010/02/08 12:03 Delete

    Zolpidem and sleepwalking. Zolpidem fedex. Zolpidem. Zolpidem abuse. Zolpidem with alcohol. Zolpidem ambien.

  129. Valtrex.

    Tracked from Valtrex. 2010/02/08 12:20 Delete

    Valtrex.

  130. Valtrex.

    Tracked from Valtrex. 2010/02/09 05:36 Delete

    Valtrex. Side effects of valtrex.

  131. Long term use of valtrex.

    Tracked from Valtrex and weight loss. 2010/02/09 23:05 Delete

    Valtrex dosing. Valtrex. Valtrex interactions. Valtrex side effects. Dosage for valtrex oral. Buy valtrex online. Valtrex dosage adult.

  132. Compare brand name and generic percocet.

    Tracked from Percocet. 2010/02/10 15:08 Delete

    Fun with percocet. Adrenaline levels after percocet. Percocet withdrawal symptoms.

  133. Ultram gc ms.

    Tracked from Ultram tramadol. 2010/02/10 20:01 Delete

    Ultram. Ultram er. Ultram online. Ultram tramadol. Ultram abuse.

  134. Valtrex medication.

    Tracked from Valtrex. 2010/02/11 10:10 Delete

    Side effects for valtrex. Valtrex info. Valtrex shingles. Generic valtrex.

  135. Methotrexate side effects.

    Tracked from Methotrexate side effects. 2010/02/11 10:51 Delete

    Imuran methotrexate. Hcg levels up after shot of methotrexate.

  136. Can you snort ativan.

    Tracked from Ativan. 2010/02/11 22:55 Delete

    Ativan. Ativan withdrawal addiction. Ativan information from drugs com. Ativan withdrawal. Ativan and celexa. Ativan side effects. Ativan xanax valuim trial pack.

  137. Cheap tramadol.

    Tracked from Tramadol. 2010/02/12 08:16 Delete

    Cheap tramadol.

  138. Tramadol.

    Tracked from Tramadol. 2010/02/15 11:20 Delete

    Tramadol side effects. Tramadol hcl.

  139. Ambien.

    Tracked from Ambien cr. 2010/02/15 13:02 Delete

    Ambien cr. Ambien online. Ambien. Buy ambien online. Buy ambien.

  140. Herbal viagra.

    Tracked from Natural viagra alternatives. 2010/02/15 16:31 Delete

    Viagra. Get viagra. Generic viagra. Viagra side effects. Viagra hgh. Cheapest viagra prices.

  141. Medicine ultram.

    Tracked from Ultram. 2010/02/15 22:40 Delete

    Ultram fed ex.

  142. Tramadol.

    Tracked from Tramadol. 2010/02/16 11:59 Delete

    Tramadol.

  143. Ultram.

    Tracked from Ultram. 2010/02/16 21:03 Delete

    Ultram. Ultram 20 mg. Ultram addiction.

  144. Valtrex and ache.

    Tracked from Valtrex. 2010/02/17 10:16 Delete

    Dosage for valtrex oral. Nicole kidman valtrex.

  145. Ambien online viagra.

    Tracked from Ambien online no prescription overnight delivery. 2010/02/17 19:25 Delete

    Ambien. Ambien online. Ambien side effects. Ambien cr. Ambien hallucinations dizziness.

  146. Ultram er.

    Tracked from Ultram. 2010/02/18 04:35 Delete

    Ultram. Ultram medicine ultram.

  147. Ultram cod.

    Tracked from Ultram dosage. 2010/02/19 02:44 Delete

    Ultram er. Ultram online order. Ultram. Buy ultram online.

  148. Cialis wholesale online.

    Tracked from Cialis prescription. 2010/02/19 04:14 Delete

    Buy cialis online.

  149. Ultram 50.

    Tracked from Low dose naltrexone with ultram. 2010/02/19 18:31 Delete

    Ultram. Order ultram no prescription. Ultram pain. Buy ultram cheapest site.

  150. Finasteride propecia.

    Tracked from Finasteride mg hair. 2010/02/20 03:16 Delete

    Finasteride 1mg. Finasteride. 1mg finasteride for bph. Finasteride brand s propecia proscar side effects. Propecia side effects finasteride. Generic finasteride.

  151. Tramadol.

    Tracked from Tramadol. 2010/02/20 10:00 Delete

    Comparative potencies of opioids tramadol. Tramadol side effects. Tramadol. Cheap comment message preview tramadol.

  152. Buying viagra online.

    Tracked from Buy viagra online. 2010/02/20 16:28 Delete

    Online viagra. Buy viagra online. Viagra online cheap.

  153. Drug treatment for valtrex.

    Tracked from Buy valtrex. 2010/02/20 18:33 Delete

    Valtrex. Buy valtrex com. Valtrex information. Valtrex 500. Valtrex side effects. Side effects of valtrex. Buy valtrex.

  154. Flight tickets online.

    Tracked from Flight tickets online. 2010/02/21 11:07 Delete

    Flight tickets online.

  155. Ultram.

    Tracked from Ultram and withdrawal. 2010/02/21 12:13 Delete

    Ultram. Ultram er. Buy ultram cheapest site. The mondego group wiki xwiki buy ultram. Buy ultram.

  156. Buy phentermine online.

    Tracked from Buy cheap phentermine. 2010/02/21 19:51 Delete

    Buy phentermine. Blue phentermine gt buy phentermine online. Buy phentermine mg. Buy generic phentermine bloghoster.

  157. Suicide ambien.

    Tracked from Generic ambien. 2010/02/21 20:48 Delete

    Buy ambien without a prescription. Wellbutrin together with ambien suicide. Ambien. Ambien and the menstrual cycle. Ambien no prescription needed.

  158. Viagra online discount.

    Tracked from Viagra sales online. 2010/02/22 09:03 Delete

    Cheap viagra lowest prices online.

  159. Valtrex.

    Tracked from Valtrex odor. 2010/02/22 12:27 Delete

    Valtrex.

  160. Cheap valtrax.

    Tracked from Cheap valtrax. 2010/02/22 17:59 Delete

    Cheap valtrax.

  161. Klonopin.

    Tracked from Klonopin. 2010/02/23 04:52 Delete

    Klonopin side effects. Xanax with klonopin. Klonopin. Klonopin sr prescribing information. Lethal dose klonopin.

  162. Cheap xanax.

    Tracked from Uhi foundation forums xanax cheap phentermine. 2010/02/23 08:00 Delete

    Cheap xanax. Hysbysfwrdd cymrux xanax cheap phentermine. Cheap generic xanax 2mg bars. Cheap no prescription xanax order online. Price comparison for xanax as well as viagra cheap. Buy cheap xanax without prescription.

  163. Buy ambien 12.5 mgm overnight mail md consultation.

    Tracked from Ambien next day delivery where. 2010/02/23 12:58 Delete

    Buy ambien without a prescription. Ambien us pharmacy. Ambien overdose. Ambien. Ambien addiction. Ambien and side effects. Ambien cr. Buy ambien without prescription.

  164. Card master no phentermine prescription.

    Tracked from Phentermine without prescription. 2010/02/23 17:38 Delete

    Phentermine no prescription. Phentermine free consultation. Phentermine dosage. Phentermine. Phentermine cheap no prescription. Buy phentermine.

  165. Can you inject klonopin wafer.

    Tracked from Klonopin. 2010/02/24 02:10 Delete

    Klonopin side effects. Online klonopin fed exed over night. Klonopin and suicide. Klonopin lethal dose. Does klonopin deplete potassium. Can you inject klonopin wafer.

  166. Voyforums buy viagra online.

    Tracked from Where can i buy gneric viagra usa. 2010/02/24 13:14 Delete

    Viagra buy.

  167. Ativan effects.

    Tracked from Ativan. 2010/02/24 15:09 Delete

    Ativan information. Buy ativan online. Ativan.

  168. Cheapest phentermine online.

    Tracked from Phentermine online pharmacy. 2010/02/24 23:07 Delete

    Buy cheap phentermine online lowest prices. Buy phentermine online. Online phentermine. Phentermine online pharmacy. Cheap phentermine online. Cheapest phentermine online.

  169. Ativan migraines.

    Tracked from Ativan. 2010/02/24 23:10 Delete

    Ativan dosage. Ativan addiction. Ativan migraines.

  170. Cheap viagra.

    Tracked from Fast and cheap viagra. 2010/02/25 11:12 Delete

    Cheap viagra. Search results dirt cheap viagra. Buy cheap viagra. Fast and cheap viagra.

  171. Klonopin.

    Tracked from Klonopin. 2010/02/25 13:43 Delete

    Klonopin side effects. How can i kill myself with klonopin. Klonopin.

  172. About glaxosmithkline pharmaceuticals and levitra.

    Tracked from Online pharmacy cost levitra. 2010/02/25 17:42 Delete

    Zoloft levitra pe cure. Levitra. Levitra online consultation.

  173. Codeine and heroin.

    Tracked from Robitusin with codeine. 2010/02/25 23:10 Delete

    Can motrin be taken with codeine. Codeine cough syrup. Hard to annunciate fioricet codeine. Buy 222 codeine. Codeine. Smoking codeine. Allergy to codeine. Somas do they have codeine in them.

  174. Price comparison for xanax as well as viagra cheap.

    Tracked from Http cheap-xanax.idemna.com xanax.html. 2010/02/25 23:11 Delete

    Cheap xanax. Xanax buy xanax online discoint xanax cheap. Cheap generic xanax 2mg bars. Forum akgl cars toyota xanax phentermine cheap. Buy cheap xanax. Cheap xanax online buy cheap xanax buy cheap xanax.

  175. Buy ultram.

    Tracked from Jh solutions buy ultram online. 2010/02/26 11:43 Delete

    Buying ultram no prescription. Buy ultram. Buy ultram online.

  176. Klonopin depersonalization derealization.

    Tracked from Klonopin. 2010/02/26 13:41 Delete

    Order klonopin without prescription. Librium vs klonopin. Klonopin lynx discussion board. Klonopin and alcoholic. Klonopin. Generic klonopin clonazepam with no prescription. Medication klonopin.

  177. Buy cheap phentermine online.

    Tracked from Order phentermine phentermine online. 2010/02/26 21:51 Delete

    Phentermine online. Buy c 20heap phentermine online. Phentermine online no prescription. Order phentermine online.

  178. Ativan data.

    Tracked from Ativan for neck pain. 2010/02/26 23:07 Delete

    Ativan. Ativan benefits. Ativan half life. Adderal ativan. Drug dosage for ativan.

  179. Carisoprodol buy cheap carisoprodol order online.

    Tracked from Carisoprodol buy cheap carisoprodol order online. 2010/02/27 14:33 Delete

    Carisoprodol buy cheap carisoprodol order online. Cheap carisoprodol.

  180. Online pharmacy oxycodone.

    Tracked from Online consultation oxycodone. 2010/02/27 21:54 Delete

    Oxycodone online without a prescription. Online pharmacy oxycodone. Oxycodone online. Buy oxycodone online without.

  181. Buy fioricet online.

    Tracked from Fioricet online. 2010/02/28 14:07 Delete

    Fioricet online.

  182. Buy valtrax.

    Tracked from Buy valtrax. 2010/03/01 01:53 Delete

    Buy valtrax.

  183. Buy valtrax.

    Tracked from Buy valtrax. 2010/03/01 10:39 Delete

    Buy valtrax.

  184. Online phentermine.

    Tracked from Phentermine cod. 2010/03/01 21:57 Delete

    Phentermine online. Phentermine 37 5mg. Phentermine. Phentermine capsule. Phentermine weight loss pill. Phentermine pregnancy. Phentermine information.

  185. Purchase vicodin online.

    Tracked from Legal meds online usa vicodin. 2010/03/02 10:38 Delete

    Vicodin online no prescription. Prescriptions drugs pharmacy online vicodin. Buy vicodin online. Buy vicodin online without. Online vicodin. Purchase vicodin online. Lorcet vicodin online.

  186. Generic fioricet.

    Tracked from Order fioricet. 2010/03/02 19:29 Delete

    Order c o d fioricet. Purchase fioricet online without prescription. Fioricet overnight. Order fioricet 32.

  187. Buy ultram online.

    Tracked from Buy ultram. 2010/03/03 15:09 Delete

    Buy fast online ultram. Buy ultram. Buy ultram online. Buy ultram 50mg.

  188. Buy ephedra stackers cheap.

    Tracked from Buy ephedra stackers cheap. 2010/03/04 10:20 Delete

    Buy online cheap yellow swarms with ephedra. Buy ephedra stackers cheap. Pure ephedra buy online cheap.

  189. Cheap viagra.

    Tracked from Viagra cheap. 2010/03/04 19:34 Delete

    Viagra cheap.

  190. Generic xanax.

    Tracked from Xanax. 2010/03/05 09:37 Delete

    Xanax dosage. Xanax no prescription. Xanax.

  191. Best online casino bonus.

    Tracked from Internet casino http. 2010/03/05 18:44 Delete

    Casino guide http. Web casino http.

  192. Buy oxycodone online without.

    Tracked from Buy oxycodone without a prescription. 2010/03/06 09:08 Delete

    Buy oxycodone online. Buy oxycodone without prescription. Buy oxycodone.

  193. Flight tickets online.

    Tracked from Flight tickets online. 2010/03/07 07:45 Delete

    Flight tickets online.

  194. Cheap viagra.

    Tracked from Viagra. 2010/03/07 10:01 Delete

    Viagra dosage. Viagra. Cheap viagra. How viagra works. Re viagra cello.

  195. Cheap phentermine diet pill.

    Tracked from Cheap phentermine. 2010/03/07 16:17 Delete

    Cheap ... phentermine cod url. Buy cheap online phentermine. Cheap phentermine c o d payment. Cheap free phentermine shipping. Buy cheap phentermine. Cheap phentermine diet pill.

  196. Buy cheap phentermine.

    Tracked from Cheap phentermine. 2010/03/08 08:57 Delete

    Cheap phentermine. Cheap phentermine yellow. Buy cheap phentermine online. Cheap phentermine online 37 5. Order phentermine online buy cheap pharmacy here.

  197. Buy cheap xanax.

    Tracked from Cheap xanax. 2010/03/08 17:32 Delete

    Cheap xanax online. Hysbysfwrdd cymrux xanax cheap phentermine. Buy cheap generic xanax. Cheap xanax fast delivery. Buy cheap xanax without prescription.

  198. Ultram buy cheap no prescription.

    Tracked from Cheap ultram. 2010/03/09 09:08 Delete

    Cheap cod ultram. Ultram buy cheap no prescription. Order ultram cheap pharmacy. Ultram buy ultram online order cheap ultram.

  199. Buy cheap phentermine.

    Tracked from Cheap phentermine cod. 2010/03/09 09:40 Delete

    Buy cheap phentermine. Phentermine pill buy cheap phentermine. Phentermine cheap.

  200. Tramadol.

    Tracked from Canine tramadol. 2010/03/09 12:58 Delete

    Buy tramadol. Tramadol side affects. Tramadol. Tramadol cheap no rx.

  201. Cheap phentermine.

    Tracked from Get phentermine. 2010/03/10 09:52 Delete

    Cheap phentermine diet pill. Phentermine. Phentermine yellow.

  202. Effects of xanax.

    Tracked from Xanax. 2010/03/10 10:19 Delete

    Xanax side effects. Xanax while pregnant. Xanax online. Xanax cocktail. Xanax. Xanax effect.

  203. Phentermine 37.5 mg online prescription.

    Tracked from Phentermine online pharmacy. 2010/03/10 19:42 Delete

    Order phentermine online. Phentermine online. Buy phentermine online. Phentermine diet pills buy online. Online phentermine. Buy phentermine online discount cheap pharmacy. Buy phentermine order cheap online. Adipexdrug addiction order phentermine online.

  204. Buy vicodin.

    Tracked from Buy vicodin no prescription. 2010/03/11 09:48 Delete

    Buy 15mg vicodin with a doctor consent. Buy vicodin without a prescription. Buy vicodin without script. Buy vicodin.

  205. Viagra online add to cart.

    Tracked from Buy viagra online. 2010/03/11 10:23 Delete

    Purchase viagra online. Buy cheap viagra online uk. Online viagra. Viagra online. Order viagra online.

  206. Buy lortab.

    Tracked from Buy lortab. 2010/03/11 11:12 Delete

    Buy lortab.

  207. Cialis discount american pharmacy.

    Tracked from Cialis. 2010/03/12 01:29 Delete

    Buy cialis phentermine. Buy cialis. Cheapest cialis. Cialis best price buy online. Taking viagra with cialis. Online pharmacy cialis on line. Cialis.

  208. Cheap online generic viagra.

    Tracked from Cheap viagra. 2010/03/12 04:51 Delete

    Cheap viagra. Buy viagra cheap. Cheap viagra discount.

Comments List

  1. tsohr 2009/01/24 11:40 # M/D Reply Permalink

    이런 좋은 문서를... 공개되도 괜찮은가요? 장난아니네요 ㄷㄷ;
    그런데, DLL 인젝션이나 다른 프로세스의 메모리를 읽는 행위도 해킹에 포함되는 내용같은데, 안티해킹도 해킹의 범주인가요?

Leave a comment
« Previous : 1 : 2 : 3 : 4 : 5 : ... 251 : Next »