태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

커널모드와 유저모드(사용자모드) 정리

CAT-Security/미분류|2014.07.14 17:59




유저 애플리케이션이 운영체제에 치명적인 데이터에 접근하여 수정하거나 삭제하지 못하게 막기 위해 윈도우는 두가지 프로세서 접근 모드를 지원 한다. 유저 어플리케이션은 유저모드에서만, 운영체제 코드(시스템 서비스와 디바이스 드라이버)는 커널 모드에서 실행이 된다. 커널 모드는 모든 시스템 메모리와 모든 CPU 인스트럭션에 접근이 허가된 프로세스 실행 모드를 말한다. (한마디로 admin) 즉 프로세서는 유저 모드보다 커널모드에 높은 권한을 줌으로써 오동작을 유발하는 유저 어플리케이션등이 시스템 전체에 안전성을 해치지 않게 보장하는 필수 기반을 운영체제 설계자에게 제공 한다.



각 프로세스들은 고유한 개별 메모리 공간을 가지지만 커널 모드 운영체제와 디바이스 드라이버 코드는 단일 가상주소 공간을 공유 한다. 가상 메모리 내의 각 페이지에는 페이지를 읽고 쓰기 위해 프로세서가 가져야하는 접근 모드가 무엇인지 표시가 되어있으며, 시스템 공간의 페이지는 커널모드에서만 접근 가능 하다.

즉 유저모드에서는 커널모드에서 접근 할 수있는 메모리 공간에 접근 하지 못한다.


유저 애플리케이션은 시스템 서비스를 호출할 때 유저모드에서 커널모드로 전환 됩니다. 예를 들면 윈도우 ReadFile함수는 실제로 파일로부터 데이터를 읽는 기능을 처리할 내부 윈도우 루틴의 호출이 필요 합니다. 이 루틴은 시스템 데이터 구조체에 접근하므로 커널모드에서 실행되어야 하며, 유저모드에서 커널모드로의 변환은 프로세서를 커널모드로 전환하게 하는 특별한 프로세서 인스트럭션의 사용으로 가능해 진다. 운영체제는 이 인스트럭션을 통해 시스템 서비스가 요청 됐음을 알아채고 스레드가 시스템 함수에 건넨 인자를 검증 한 후 내부 함수를 실행 한다. 제어를 다시 유저 스레드로 되돌리기전에 프로세서는 다시 유저모드로 전환 된다. 이 방법으로 운영체제는 그 자체와 데이터를 사용자 프로세스가 들여다보거나 변경하지 못하게 보호 한다.


유저모드와 커널모드로의 전환과 되돌림은 스레드 스케줄링에 영향을 미치지 않는다. 모드 전환은 컨텍스트 변경이 아니다.



유저 모드는 다음과 같은 특징을 갖는다.


1. 사용자 애플리케이션 코드가 실행 한다.

2. 시스템 데이터에 제한된 접근만이 허용되며 하드웨어를 직저 접근 할수 없다.

3. 유저 애플리케이션은 시스템 서비스 호출을 하면 유저모드에서 커널 모드로 전환 된다.

4. CPU 유저 모드 특권 수준으로 코드를 실행 한다.

5. 유저모드 에서 실행하는 스레드는 자신만의 유저모드 스택을 가진다.


커널 모드는 다음과 같은 특징을 갖는다.


1. 시스템의 모든 메모리에 접근 할 수있고 모든 CPU 명령을 실행 할 수 있다.

2. 운영체제 코드나 디바이스 드라이버 같은 커널 모드 코드를 실행 한다.

3. CPU는 커널 모드 특권 수준에서 코드를 실행 한다.






ex : CreateXXX()계열 함수를 호출하면 이 호출 되는 시점은 유저모드에서 실행 되지만, 이 함수가 실행되면 커널모드로 전환되서 커널에게 오브젝트 생성을 요청 한다. 그리고 커널에서 만들어지든 실패하든 결과가 나와서 함수가 리턴되면 바로 자동으로 유저모드로 돌아오게 된다.



댓글(1)

[Python] BeautifulSoup 모음

CAT-Security/미분류|2014.06.01 16:15




한글이 깨졌을 경우


Url_html = urllib2.urlopen(Url).read().decode('cp949', 'ignore')



출처 : 클릭

댓글(0)

[윈도우 후킹] Message hooking - 1

CAT-Security/미분류|2014.05.19 21:03





0x00 후킹의 개념


후킹은 소프트웨어 공학 용어로, 운영 체제나 응용 소프트웨어 등의 각종 컴퓨터 프로그램에서 소프트웨어 구성 요소 간에 

발생 하는 함수 호출, 메세지, 이벤트 등을 중간에 바꾸거나 가로채는 명령, 방법, 기술이나 행위를 말한다. 

이때 이러한 간섭된 함수 호출, 이벤트 또는 메세지 처리하는 코크를 후크라고 한다.

크래킹을 할떄 크래킹 대상 컴퓨터의 메모리 정보, 키보드 입력 정보등을 뺴돌리기 위해서 사용 되기도 한다. 

예를 들어 특정한 API를 하쿵 히가 되면 해당 API의 리턴값을 조작하는 등의 동작을 수행 할 수 있다.(위키백과 펌)


다른 프로세스의 실행 경로를 가로 채는 것을 말 합니다.

대표적인 예로 키로거,매크로, 원격 등이 있습니다. 종류는 구성 요소간에 발생 되는 모든것을 할 수 있습니다.

메세지 후킹, API후킹, 네이티브 API 후킹, 인터럽트 후킹 등이 있으며 여기서 다뤄 볼 것은 메세지 후킹 입니다.



0x01 메세지 훅


Windows 운영체제는 GUI 를 제공하고, 이것은 Event Driven 방식으로 동작 합니다.

키보드/마우스를 이용하여 메뉴 선택, 버튼 선택, 마우스 이동창, 창 크기 변경, 창 위치 이동등의 작업은 모두 이벤트 입니다.

이러한 이벤트가 발생할 떄 OS는 미리 정의된 메세지를 해당 응용 프로그램으로 통보 하며 

여기서 중요 한것은 사용자의 입력은 언제나 한가지 윈도우에게만 반응 한다는 것 입니다.

사용자의 키보드 입력과 마우스 입력이 동시에 두개의 윈도우로 전달되는 일은 없고 응용 프로그램은 해당 메세지를 분석하여 필요한 작업을 진행 합니다


메세지 훅이란 바로 이러한 메세지를 중간에서 엿보는 것 입니다.




다음은 일반적인 경우의 Windows 메세지 흐름에 대한 설명 입니다.


1. 키보드 입력 이벤트가 발생하면 WM_KEYDOWN 메세지가 [OS message queue]에 추가

2. OS는 어느 응용 프로그램에서 이벤트가 발생 했는지 파악 후 [OS message queue]에서 메세지를 꺼내 해당 응용 프로그램의 [application message queue]에 추가

3. 응용 프로그램은 자신의 [application message queue]를 모니터링 하고 있다가 WM_KEYDOWN 메세지가 추가 된 걸 확인하고 해당 event handler를 호출




_이벤트


이벤트라는 것은 O/S에서 처리하는 일련의 반응입니다. 

예를 들면 O/S상의 메모장에서 X 버튼을 누르면 메모장이 닫히게 되는데, X 버튼 이미지 자체에 메모장을 종료하는 기능이 있는게 아니라 

이 구역을 누름으로써 메모장을 종료하는 이벤트를 실행 하게 되는 것 입니다.

바로 이 이벤트를 후킹 하면 X 버튼을 누르면 메모장을 종료 하는 것이 아닌 다른 이벤트가 실행 되게 할 수 있습니다.




0x02 메모리 공간의 분리


WIn16 환경에서는 모든 공간은 한 메모리(같은주소 공간)에 있었습니다.

이러한 시스템에서 가장 큰 단점은 한 프로세스의 오류가 다른 프로세스에게 까지 영향을 미친 다는 것 이였으며 

사용자가 버퍼를 넘어 입력 한 값이 다른 프로세스의 공간 일 수가 있었 던 것 입니다.

이러한 문제점을 해결 하기 위해서 WIn32 환경에서는 모든 프로세스의 주소 공간을 분리 시켰습니다.





쉽게 말하면 모든 프로세스가 독립적인 4GB 메모리 공간을 가진 다는것 입니다. 

즉 실행 프로세스 개수 * 4GB 만큼의 메모리가 있는 것같은 환경을 운영체제가 제공 해 준다는 것 입니다.

이와 같은 메모리 공간의 분리는 운영체제의 경고함에 힘을 실어 줬지만 일견에서는 다른 프로세스를 후킹 하기가 더 어려운 환경이 되었고 

이러한 문제점을 해결 하기 위해 Microsoft에서는 몇가지 방법을 제안 했습니다.

자신들이 제시한 API를 사용 하면 합법적으로 다른 프로세스의 주소 공간으로 초대 해 준 다는 것 입니다.


주의 할점은 다른 프로세스를 후킹하기 위해서는 훅 프로시저는 반드시 DLL 내부에 존재 해야하며, 

그래야만 운영체제가 해당 DLL을 다른 프로세스에서 로드 시켜서 훅 프로시저를 호출 할 수 있기 때문입니다.

그리고 DLL 내부에 있는 훅 프로시저가 호출 되는 쓰레드 컨텍스트는 임의의 쓰레드 라는 점 입니다. 

즉 자신이 훅 함수를 호출 한 프로시저의 쓰레드가 아닌 이벤트가 발생한 쓰레드라는 점 입니다.



댓글(2)

[PlaidCTF 2013] three eyed fish_100

CAT-Security/미분류|2014.05.16 16:56






문제는 64bit elf 파일이며, stripted가 걸려 있는 파일 입니다.




실행시 아무런 반응이 없어서 strace로 실행을 시켜 보았습니다.




ptrace(PTRACE_TRACEME, 0, 0, 0) 에서 에러가 남을 확인 할 수 있습니다.

찾아보니까 주어진 프로세스에 대한 UDI가 현재 사용자의 UID와 매칭되지 않으면 다음과 같은 에러가 뜨는 것 입니다. 

단순히 UID만을 검사 하는것이면은 프로그램에서 '없어도' 될것이라 판단이 되며 코드패치로 삭제시켜 보았습니다.





objdump로 함수 주소를 찾아도되고, IDA64에서 찾아도 무방 합니다.





찾아서 이렇게 NOP코드로 변환 시켜주게 되면 저 함수는 실행되지 않고 그냥 지나치게 되어 버립니다.





UID 검사 루틴을 제거해주니, 비정상적인 종료를 하지않고 프로그램이 제대로 돌아가게 되었습니다.




이 다음부터는 제가 푼것이 아니라 

블로그 : http://f00l.de/blog/plaid-ctf-2013-three_eyed_fish/ 

writeup을 보고 풀었습니다





결론적으로 모스부호로 된 암호 였습니다.






strace의 모든 내용을 fish.txt에 담고, 내용을 살펴보면




다음과 같이 모스 부호를 뽑아 낼 수 있습니다.

ioctl으로 led를 구현 한것 같은데, 솔찍히 잘 모르겠네요..





자세한 설명 입니다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/perl
 
$on = "ioctl(3, KDSETLED, 0x4)";
$off = "ioctl(3, KDSETLED, 0)";
$sleep = "nanosleep({0, 250000000}";
 
open(LOG, "fish.txt");
 
$state = "OFF";
$timer = 0;
while($line = <LOG>) {
  if (substr($line, 0, length($on)) eq $on) {
    if ($state eq "OFF") {
      if ($timer == 3) { print " "; }
    }
    $timer = 0;
    $state = "ON";
  }
  if (substr($line, 0, length($off)) eq $off) {
    if ($state eq "ON") {
      if ($timer == 1) { print "."; $timer = 0; }
      if ($timer == 3) { print "-"; $timer = 0; }
    }
    $state = "OFF";
  }
  if (substr($line, 0, length($sleep)) eq $sleep) {
    $timer++;
  }
}
print "\n";
close(LOG);


모스 부호를 뽑아 내는 프로그램은 다음과 같습니다.






Key is : AND0U0DIDNT0EVEN0NEED0AN0ARDUINO


'CAT-Security > 미분류' 카테고리의 다른 글

[Python] BeautifulSoup 모음  (0) 2014.06.01
[윈도우 후킹] Message hooking - 1  (2) 2014.05.19
[PlaidCTF 2013] three eyed fish_100  (0) 2014.05.16
[CSAW CTF 2012] Reversing_400  (0) 2014.05.15
[Codegate2014] dodoCrackme_200  (0) 2014.05.13
[Reversing.kr] Direct3D_FPS  (6) 2014.05.08

댓글(0)

[CSAW CTF 2012] Reversing_400

CAT-Security/미분류|2014.05.15 15:39







문제는 64bit, not stripped 파일 입니다





실행시 암호화된 Key값이 보입니다. 단순히 Key값만을 출력해줌을 알 수 있습니다.





IDA64로 디버깅 했을시, 단순히 값들을 입력받고 encrypt 함수를 실행시켜서 암호화 한후 그 결과값을 출력 해 줍니다.






허나 이 문제의 경우 encrypt 함수가 있고 decrypt함수도 존재 합니다.

즉 encrypt를 Call 하는 부분을 강제로 decrypt로 eip를 바꾸게 되면 키값이 decrypt가 될것이라 생각 했습니다.






gdbserver로 리모트 디버깅을 시도해서 eip를 강제로 decrypt쪽으로 분기 시키니까 키값이 보이게 되었습니다.



다른 방법으로는 코드패치가 있었습니다.

출처 : http://havu.tistory.com/28






Encrypted Key 를 출력 해 준 이후, call done을 하게 되는데, 이 done함수에는 exit를 포함 하고 있습니다.

그래서 프로그램이 종료가 되게 되는데, 4006BE ~ 4006C2까지 hex뷰를 열어서 지워보겠습니다.





코드는 다음과 같이 바뀌게 됩니다.





실행을 했을시 정상적으로 Decrypt가 됩니다.


'CAT-Security > 미분류' 카테고리의 다른 글

[윈도우 후킹] Message hooking - 1  (2) 2014.05.19
[PlaidCTF 2013] three eyed fish_100  (0) 2014.05.16
[CSAW CTF 2012] Reversing_400  (0) 2014.05.15
[Codegate2014] dodoCrackme_200  (0) 2014.05.13
[Reversing.kr] Direct3D_FPS  (6) 2014.05.08
[Secuinside2013] beist_attack_game_150  (0) 2014.05.02

댓글(0)

[Codegate2014] dodoCrackme_200

CAT-Security/미분류|2014.05.13 19:46










프로그램은 다음과 같이 64-bit elf파일이며 stripped가 걸려 있습니다.




실행을 했을 떄 입력을 받으며 Permission denied을 출력하며 프로그램이 종료 됩니다..






strace로 확인 했을 때 write와 와 read가 보임을 확인 할 수 있습니다.






IDA 64로 열어봤을 때, 이러한 루틴이 반복됨을 확인했고, 증가 된 값을 메모리 어딘가에 저장을 합니다.

반복되었기 때문에 찍히는 문자열을 보았고, 키값이 나왔습니다.






허나 이 방식은 제대로 된 풀이 방법이 아니기 때문에, 타 블로그에 있는 정상적인 방법을 쓰겠습니다.

출처 : http://pwnbit.kr/42






write의 경우 호출값은 1이며 read는 0 입니다.

다음은 64bit 환경 리눅스에서 read 및 함수들이 어떻게 호출 되는지 볼 수 있는 사이트 입니다.

linux system call table for x86-64 : http://blog.rchapman.org/post/36801038863/linux-system-call-table-for-x86-64


 




다음과 같은 형식으로 호출 됨을 확인 할 수 있습니다.





mov     eax, 0 (mov 띄어쓰기 다섯번)

0x4065C0의 주소값에서 read함을 알 수 있습니다.






read()에 break point를 걸고, 200개만큼 cw로 출력을 하니 키값이 나옴을 확인 할 수 있습니다.

이것의 경우 ebp 기준으로, 바로 밑에 char key="H4PPY_C0DEGaTE_2014_CU_1N_K0RE4" 식으로 되어있을 것 입니다.


블로그의 작성자는 read()함수를 쓸때 ebp값을 보게 되면 어딘가에서 비교할테니 값을 출력 할것이다 라고 생각을 했는데,

내 생각은 조금 다르다, 어차피 이 프로그램은 사용자 정의함수등이 따로 구현되어 있는것 같지가 않습니다.

그 증거로 break point를 거의 맨 아래부분인 b *0x040b744 에 걸고 x/200cw $rbp를 해도 키값이 출력됨을 확인 할 수 있습니다.


즉 그렇다면 단순히 프로그램내에서 ebp와 멀지않는 곳의 키값을 출력하는것이 핵심 인 것이고,

read의 주소값을 굳이 확인하지 않더라도 프로그램이 끝나가는 부분이라던지 어느 지점부분에서 ebp를 출력하면 키값을 확인 할 수 있을 것 입니다.




'CAT-Security > 미분류' 카테고리의 다른 글

[PlaidCTF 2013] three eyed fish_100  (0) 2014.05.16
[CSAW CTF 2012] Reversing_400  (0) 2014.05.15
[Codegate2014] dodoCrackme_200  (0) 2014.05.13
[Reversing.kr] Direct3D_FPS  (6) 2014.05.08
[Secuinside2013] beist_attack_game_150  (0) 2014.05.02
gdb 명령어 요약집  (0) 2014.04.28

댓글(0)

[Reversing.kr] Direct3D_FPS

CAT-Security/미분류|2014.05.08 15:57



프로그램을 실행 시키면 다음과 같은 3D_FPS 게임이 시작 되게 됩니다.

저 달걀(?)을 몇방 쏘면 사라지며 게임내의 모든 달걀들을 없에더라도 클리어가 되질 않습니다.


또한 HP10은 달걀과 몸을 부딕쳤을 경우 피가 소모 됩니다.

상단바 위의 ReversingKr / FPS는 값이 시시각각 변하긴 하는데 그닥 중요한 값이 아니라 생각이 들었습니다.





Ollydbg의 막강한 기능중 하나인 Search for all referenced string를 이용하여 Game Clear 부분을 따라 가보았고

그곳으로 억지로 강제로 분기를 조작하여 출력을 했더니 이상한 값을 출력 했습니다.

이 이상한 값을 메모리 덤프에서 검색을 해 보았더니 00407028의 주소값에 있는 값을 출력함을 알 수 있었습니다.



스크린샷을 찍으면서 보니 MessageBox함수에 PUSH 00407028이 보이네요^^;; (왜 검색했지..)



이 값들을 분명히 바꿔주는 무언가가 있을꺼라 생각했고 현재 게임상에서 달걀을 죽이는것 밖에 없으니 달걀을 마구마구 쏴댔습니다.

그 결과 달걀 하나를 죽일때마다 값이 하나씩 바뀜을 알 수 있었습니다.


이 값들중 하나에 Hard Brack Point를 걸어서 값을 직접적으로 바꿔주는곳을 찾아 보았습니다.




그 결과 XOR BYTE PTR [EAX+407028], CL의 부분에서 값을 바꿔줌을 확인 할 수 있었습니다.



소스코드를 해석하자면은 00403440의 함수에서 내가 쏜 달걀의 주소값을 가져 옵니다.

가령 첫번째 달걀은 0x01, 27번째 달걀은 0x1B의 값을 eax에 리턴 해 줍니다.

리턴한 eax값을 ecx로  복사 한 후  210을 곱해주고, 그 값과 +409190을 하여서 있는 달걀의 피를 -2씩 해줍니다.

달걀의 피가 0이 되었을때, eax에 210을 곱한값 + 409184에 있는 값을 가져와서 eax+407028의 값과 xor을 해 줍니다.




맵에 있는 모든 달걀을 학살(?)하니 다음과 같이 Congratulation Game Clear! Pass word is Thr3EDPr이라는 스트링값이 나왔습니다.

신나게 인증을 하려 했지만 Thr3EDPr로는 인증이 되질 않았습니다.


????


하던 찰나에


407058주소에 있는 F0과 A9가 보이게 되었고, 저 값을 저 알고리즘에 맞추어서 수동으로 바꾸어 주니

Thr3EDPr0m 이라는 Password 를 얻을 수 있었습니다.

'CAT-Security > 미분류' 카테고리의 다른 글

[CSAW CTF 2012] Reversing_400  (0) 2014.05.15
[Codegate2014] dodoCrackme_200  (0) 2014.05.13
[Reversing.kr] Direct3D_FPS  (6) 2014.05.08
[Secuinside2013] beist_attack_game_150  (0) 2014.05.02
gdb 명령어 요약집  (0) 2014.04.28
[Defcon 21 ctf] policebox  (0) 2014.04.08

댓글(6)

[Secuinside2013] beist_attack_game_150

CAT-Security/미분류|2014.05.02 16:41







프로그램을 실행 시키면 다음과 같은 게임 화면이 나오게 됩니다.

점수 획득이 가능하며 1000점을 달성했을 시에 보스몹이 나오게 되고

그 보스몹의 피는 999999 입니다.


보스몹은 전체공격(?)을 시전해서 정상적인 방법으로

도저히 클리어가 불가능합니다.





보스몹 출현!!






보스몹의 피를 깍는건 거의 불가능 합니다.







현재 게임에서 볼수 있는 단서는 점수라고 생각하고

그 점수값이 1000점이 되었을때 새로운 함수가 실행 된다라는 생각이 들어서

점수를 중심적으로 찾아 보았습니다.


예상대로 1000점이었을경우 if문 안으로 분기해서 보스몹을 띄우는 루틴을 찾을 수 있습니다.





여러 루틴을 살피던 도중에 스코어 값이 20점이 되었을때 406450의 메모리의 값을

바꿔버리는 루틴을 찾을 수 있었습니다.




바뀐 이후의 메모리 값 입니다.





밑을 조금더 살펴 보게 되면은, 바뀐 값에 또 += 18로 바꾸는 것을 볼 수 있습니다.

그리고 그 밑에 406450 메모리의 값을 String에 넣고 TextOut 해주는것을 볼 수 있습니다.

999999의 피를 다 깍은 이후의 출력될 값으로 예상 됩니다.







메모리 값을 가져와서 +=을 해 줬습니다.





키값이 출력 됨을 확인 할 수 있었습니다.





치트엔진으로 메모리값만 바꾸어도 키값을 출력 합니다.






'CAT-Security > 미분류' 카테고리의 다른 글

[Codegate2014] dodoCrackme_200  (0) 2014.05.13
[Reversing.kr] Direct3D_FPS  (6) 2014.05.08
[Secuinside2013] beist_attack_game_150  (0) 2014.05.02
gdb 명령어 요약집  (0) 2014.04.28
[Defcon 21 ctf] policebox  (0) 2014.04.08
Python 예외처리  (0) 2014.01.09

댓글(0)

gdb 명령어 요약집

CAT-Security/미분류|2014.04.28 14:31

1. 우선 컴파일 시에 디버깅 정보를 담아야 한다.
 gcc -g -o [프로그램명] [소스파일명]
 디버깅 옵션인 -g 으로 컴파일하며, 최적화 옵션인 -O 은 주지 않도록 한다.

2. 실행방법
 gdb [프로그램명]
 gdb [프로그램명] [core파일명]
 gdb [프로그램명] [실행중인프로세스pid]


3. 종료방법
 q
 Ctrl + d

4. 소스 찾아가기 (list)
 l   : main 함수를 기점으로 소스의 내용이 출력된다
 l 10  : 10 행 주변의 소스가 출력되는데 10 - 5 행부터 10 + 5행까지 총 10행이 출려된다.
 l func  : func 함수의 소스를 출력
 l -5  : 기본값으로 10줄이 출력된다고 가정하고, 다음에 출력될 라인이 11라인이라면, 10(마지막라인) - 5 라인을 중심으로 출력된다. 즉, 그대로 1~10라인이 출력된다.
 l a.c:func : a.c 파일의 func 함수부분을 출력
 l a.c:10 : a.c 파일의 10행을 기준으로 출력

5. 옵션
 set listsize 20 : 한번에 출력하는 행의 갯수를 20개로 늘린다.
 Enter  : 마지막으로 수행한 명령어를 다시 수행한다

6. 프로그램 실행, 종료 (run, kill)
 r   : 프로그램 수행 (재시작)
 r arg1 arg2 : arg1과 arg2를 인자로 프로그램 수행
 k   : 프로그램 수행종료

7. 역추적하기 (backtrace)
 bt   : 오류가 발생한 함수를 역으로 찾아간다.

8. 중단점 사용하기 (breakpoint, temporary breakpoint)
 b func  : func 함수에 브레이크 포인트 설정
 b 10  : 10행에 브레이크 포인트 설정
 b a.c:func : a.c파일의 func함수에 브레이크 포인트 설정
 b a.c:10 : a.c파일의 10행에 브레이크 포인트 설정
 b +2  : 현재 행에서 2개 행 이후 지점에 브레이크 포인트 설정
 b -2  : 현재 행에서 2개 행 이전 지점에 브레이크 포인트 설정
 b *0x8049000 : 0x8049000 주소에 브레이크 포인트 설정 (어셈블리로 디버깅 시 사용)
 b 10 if var == 0 : 10행에 브레이크 포인트를 설정해되, var 변수 값이 0일 때 작동
 tb   : 임시 중단점을 사용하는 것으로 한번만 설정되며, 그 이후에는 삭제된다.

9. 중단점 설정하기 (condition)
 condition 2 var == 0 : 고유번호가 2번인 브레이크포인트에 var변수가 0일 때 동작하라고 설정

10. 중단점 삭제하기 (clear, delete)
 cl func  : func 함수의 시작 부분에 브레이크 포인트 지움
 cl 10  : 10행의 브레이크 포인트 지움
 delete 1 : 고유번호 1번의 브레이크 포인트를 지운
 cl a.c:func : a.c 파일의 func함수의 브레이크 포인트 지움
 cl a.c:10 : a.c 파일의 10행의 브레이크 포인트 지움
 cl   : 모든 브레이크 포인트 지움 
11. 중단점 정보보기 (information)
 info b  : 현재 설정된 브레이크 포인트의 정보를 보여준다
 방향키Up/Down : 방향키 Up/Down을 누르면 히스토리 기능을 제공한다
 info br + TAB : info br 로 시작하는 키워드가 히스토리에 있다면 뿌려준다
 info TAB + TAB : info 뒤에 올 수 있는 인자 리스트를 보여준다
 TAB + TAB  : 현재 사용가능한 모든 명령어 리스트를 보여준다

12. 중단점 비활성화, 활성화 하기 (enable, disable)
 disable 2 : 고유번호 2번인 브레이크 포인트 비활성화
 enable 2 : 고유번호 2번인 브레이크 포인트 활성화

13. 디버깅 하기 (step, next, continue, until, finish, return, step instruction, next instruction)
 s  : 현재 출력된 행을 수행하고 멈추지만, 함수의 경우 함수의 내부로 들어가서 수행된다
 s 5  : s를 5번 입력한 것과 동일
 n  : 현재 행을 수행하고 멈추지만, 함수의 경우 함수를 수행하고 넘어간다
 n 5  : n을 5번 입력한 것과 동일
 c  : 다음 브레이크 포인트를 만날때 까지 계속 수행한다
 u  : for 문에서 빠져나와서 다음 브레이크 포인트까지 수행한다.
 finish : 현재 함수를 수행하고 빠져나감
 return : 현재 함수를 수행하지 않고 빠져나감
 return 123 : 현재 함수를 수행하지 않고 빠져나감, 단, 리턴값은 123
 si  : 현재의 인스트럭션을 수행, 함수 호출 시 내부로 들어간다.
 ni  : 현재의 인스트럭션을 수행, 함수 호출 시 내부로 들어가지 않는다.

14. 감시점 설정 (watch)
 watch i : i변수에 와치포인트를 설정하고 i변수가 바뀔 때마다 브레이크가 걸리면서 이전값과 현재값을 출력한다.

15. 변수 정보보기 (info, print)
 info locals : 현재 상태에서 어떤 지역변수들이 있으며, 값은 어떠한지를 알 수 있다.
 info variables : 현재 상태에서의 전역변수 리스트를 확인할 수 있다.
 p lval  : lval 값을 확인한다.
 p func  : func 함수의 주소값을 확인한다.
 p pt  : pt가 구조체라면 구조체의 주소를 확인한다
 p *pt  : pt가 구조체라면 구조체의 값을 확인한다.
 p **pt  : *pt가 구조체라면 구조체의 값을 확인한다.
 info registers : 레지스트 값 전체를 한번에 확인한다.

16. 레지스트 값 및 포인터가 가리키는 구조체의 배열을 출력 (info, print)
 info all-registers : MMX 레지스트를포함하여 거의 대부분의 레지스트 값을 확인한다.
 p $eax  : eax 레지스트의 값을 확인한다. ( ex_ eax, ebx, ecx, edx, eip ) 
 p *pt@4  : 4크기의 배열로 gdb가 알 수 있으므로 4개의 크기만큼 가져와서 확인할 수 있다.

17. 중복된 변수명이 있는 경우 특정 변수를 지정해서 출력 (print)
 p 'main.c'::var : main.c 파일에 있는 전역변수인 var 변수의 값을 출력
 p hello::var : hello 함수에 포함된 static 변수인 var 변수의 값을 출력

18. 출력 형식의 지정
 p/t var : var 변수를 2진수로 출력
 p/o var : var 변수를 8진수로 출력
 p/d var : var 변수를 부호가 있는 10진수로 출력 (int)
 p/u var : var 변수를 부호가 없는 10진수로 출력 (unsigned int)
 p/x var : var 변수를 16진수로 출력
 p/c var : var 변수를 최초 1바이트 값을 문자형으로 출력
 p/f var : var 변수를 부동 소수점 값 형식으로 출력
 p/a addr : addr주소와 가장 가까운 심볼의 오프셋을 출력 ( ex_ main + 15 )

19. 타입이 틀릴 경우 타입을 변환하여 출력
 p (char*)vstr : 실제 컴파일 시에 (void *)형으로 되어있었다고 하더라도 (char *)로 캐스팅 하여 보여줌

20. 특정한 위치 지정
 p lstr + 4 : 예를 들어 lstr = "I like you." 라는 문자열은 "ke you."가 출력된다.

21. 변수 값 설정
 p lval = 1000 : 변수값 확인 이외에는 설정도 가능하다.

22. 출력명령 요약 (print)
 p [변수명]    : 변수 값을 출력
 p [함수명]    : 함수의 주소를 출력
 p/[출력형식] [변수명] : 변수 값을 출력 형식으로 출력
 p '[파일명]'::[변수명] : 파일명에 있는 전역변수 값을 출력
 p [함수명]::[변수명] : 함수에 있는 변수 값을 출력
 p [변수명]@[배열크기] : 변수의 내용을 변수 배열의 크기 형태로 출력

23. 디스플레이 명령 (display, undisplay)
 display [변수명]  : 변수 값을 매번 화면에 디스플레이
 display/[출력형식] [변수명] : 변수 값을 출력 형식으로 디스플레이
 undisplay [디스플레이번호] : 디스플레이 설정을 없앤다
 disable display [디스플레이번호] : 디스플레이를 일시 중단한다.
 enable display [디스플레이번호] : 디스플레이를 다시 활성화한다.

24. 스택이란
 스택의 경우는 상위 1기가는 커널에서 사용하며, 그 바로 아래 공간인 상위 0xBFFFFFFF 부터 하위로 늘어나게된다.
 상세한 디버깅을 위해서는 -g 옵션으로 디버깅 정보와 --save-temps 옵션을 통해 어셈블리 코드를 얻어낼 수 있다.
 상위 프레임으로 갈 수록 메인 함수에 가까워 지는 것이다.

25. 스택 프레임 관련 명령 (frame, up, down, info)
 frame [N] : n번 스택 프레임으로 변경
 up   : 상위 프레임으로 이동
 up [N]  : n번 상위 스택 프레임으로 이동
 down  : 하위 프레임으로 이동
 down [N] : n번 하위 스택 프레임으로 이동
 info frame : 현재 스택 프레임 정보를 출력
 info args : 현재 스택 프레임의 함수가 호출될 때 인자를 출력
 info locals : 현재 스택 프레임의 함수내의 지역변수를 출력
 info catch : 현재 스택 프레임의 함수내의 예외 핸들러를 출력

26. 스택 트레이스 하는법
 b main 또는 원하는 곳에 브레이크 포인트를 잡고
 오류가 발생할 때 까지 c를 통해 진행하면, 세그먼트 폴트 등의 오류가 발생하고 디버그가 멈추는데
 여기서 bt 를 통해서 전체 스택 프레임을 확인하고 어떤 함수에서 호출시에 문제가 발생하였는지 확인
 단, 일반적인 라이브러리에서는 오류발생 확률이 없다고 보고, 그 함수를 호출시에 문제를 의심한다.
 다시 프레임을 이동하면서, 로컬변수와 전역변수 등을 확인하면서 디버깅이 가능하다.

27. 메모리 상태 검사 (x)
 x/[범위][출력 형식][범위의 단위] : 메모리의 특정 범위의 값들을 확인할 수 있다.
 이렇게 메모리를 직접 읽어보는 일은 -g 옵션을 가지고 컴파일 되지 않은 실행파일을 디버깅 할때에 자주 사용된다.
 즉, x/10i main 과 같이 역 어셈블하여 해당 코드를 추측하는 것이다.

28. 출력형식
 x/10 main : main 함수 시작부터 40바이트를 출력한다. 출력형식은 다음과 같다.
 x/10t main : main 함수 시작부터 40바이트를 2진수로 출력
 x/10o main : main 함수 시작부터 40바이트를 8진수로 출력
 x/10d main : main 함수 시작부터 40바이트를 부호가 있는 10진수로 출력 (int)
 x/10u main : main 함수 시작부터 40바이트를 부호가 없는 10진수로 출력 (unsigned int)
 x/10x main : main 함수 시작부터 40바이트를 16진수로 출력
 x/10c main : main 함수 시작부터 40바이트를 최초 1바이트 값을 문자형으로 출력
 x/10f main : main 함수 시작부터 40바이트를 부동 소수점 값 형식으로 출력
 x/10a main : 가장 가까운 심볼의 오프셋을 출력
 x/10s main : 문자열로 출력
 x/10i main : 어셈블리 형식으로 출력

29. 범위의 단위 (기본 word - 4바이트)
 x/10b main : byte - 1바이트 단위 - 10바이트 출력
 x/10h main : halfword - 2바이트 단위 - 20바이트 출력
 x/10w main : word - 4바이트 단위 - 40바이트 출력
 x/10g main : giant word - 8바이트 단위 - 80바이트 출력

30. 디스어셈블링 (disas)
 disas func : 어셈블리 코드를 좀 보편적으로 보기 위한 명령어
 disas 0x8048300 0x8048400 : 특정 주소 범위사이의 어셈블리 코드를 보기

31. 함수호출 (call)
 call func(arg1, arg2) : 특정함수 func를 arg1, arg2 파라메터를 포함하여 호출하고, 반환값은 출력

32. 점프 (jump)
 jump *0x08048321 : 해당 주소로 무조건 분기하여 인스트럭션을 계속 수행한다.
 jump 10  : 무조건 10행으로 분기하여 수행한다.
 jump func : func 함수로 무조건 분기하여 수행한다.

33. 시그널 전송 (signal)
 info signals : 보낼 수 있는 시그널의 종류를 확인할 수 있다.
 signal SIGKILL : 디버깅 대상의 프로세스에게 KILL 시그널을 보낼 수 있다.

34. 메모리의 특정 영역에 값을 설정 ( set )
 set {타입}[주소] = [값] : p 명령 대신에 set 을 통해서 메모리의 특정 주소에 저장하는 것이 더 일반적이다
 set {int}0x8048300 = 100 : 해당 주소에 100의 값을 입력한다.

35. gdb 환경설정 (set)
 info set : 변경 가능한 환경설정 정보를 출력한다.
 info functions : 함수들의 리스트를 출력
 info types  : 선언된 타입에 대한 리스트를 출력
 set prompt psyoblade: : 프롬프트를 psyoblade: 로 변경할 수 있다.
 set print array on : 배열을 출력할 때 한 행에 출력하는 것이 아니라 여러 행에 출력한다.

36. 기타 info 를 통해 알 수 있는 정보들
 address         catch           extensions      handle          objects         set             stack           tracepoints
 all-registers   common          files           heap            program         sharedlibrary   symbol          types
 architecture    copying         float           leaks           registers       signals         target          variables
 args            dcache          frame           line            remote-process  source          terminal        warranty
 breakpoints     display         functions       locals          scope           sources         threads         watchpoints




psyoblade님 이글루에서 펌 (http://psyoblade.egloos.com/2653919)

'CAT-Security > 미분류' 카테고리의 다른 글

[Reversing.kr] Direct3D_FPS  (6) 2014.05.08
[Secuinside2013] beist_attack_game_150  (0) 2014.05.02
gdb 명령어 요약집  (0) 2014.04.28
[Defcon 21 ctf] policebox  (0) 2014.04.08
Python 예외처리  (0) 2014.01.09
리버싱의 기초 정리  (0) 2013.07.23

댓글(0)

[Defcon 21 ctf] policebox

CAT-Security/미분류|2014.04.08 22:56




 

 분석지점

 

int __cdecl main()
{
  signed int v1; // [sp+1Ch] [bp-4h]@5

  if ( !isatty(ttyfd) )
    perror("not on a tty");
  if ( tcgetattr(ttyfd, &orig_termios) < 0 )
    perror("can't get tty settings");
  atexit(tty_exit);
  tty_raw();
  v1 = 0;
  printf("The key is: ");
  while ( v1 <= 63 )
  {
    if ( (unsigned __int8)getchar() == 13 )
    {
      puts("\r");
      return 0;
    }
    ++v1;
  }
  return 0;
}







  if ( !isatty(ttyfd) )

    perror("not on a tty");


Isatty : 파일 지정자가 터미널을 사용하는지 검사한다.

출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/3/isatty


perror 

출처 : http://itguru.tistory.com/53


#include <stdio.h> // C++ 에서는 <cstdio>

void perror ( const char * str );


인자 str

C 형식 문자열로 시스템 오류 메세지 다음에 이어서 출력할 사용자 정의 메세지이다. 
만일 널 포인터라면, 시스템 오류 메세지 다음에 어떠한 메세지도 출력되지 않는다.
관습적으로 프로그램의 이름이 인자로 주로 사용된다. 


오류 메세지를 출력한다.
전역 변수 errno 의 값을 해석하여 이에 해당하는 시스템 오류 메세지를 표준 오류 출력 스트림(standard error output stream, stderr) 에 출력한다. 보통 stderr 은 화면이다. 또한 추가적으로 전달하고자 하는 사용자 정의 메세지를 str 인자에 담아 출력할 수 도 있다. 
errno 는 정수형 변수로 이전의 라이브러리 함수에 의해 발생한 오류에 대한 정보를 가지고 있다. 이 때, errno 에 값에 따라 perror 함수에 의해 출력되는 시스템 오류 메세지는 플랫폼이나 컴파일러에 따라 달라질 수 있다.
만일 str 이 널 포인터가 아니라면 사용자 정의 메세지가 시스템 오류 메세지 이전에 출력된다. 이 때 두 개의 메세지는 ": " 로 구분된다. 그리고 str 이 널 포인터인지 아닌지에 상관 없이 맨 마지막에는 개행 문자('\n')가 출력된다. 
perror 은 오류가 발생한 바로 다음에 호출되어야 한다. 그렇지 않을 경우 다른 함수들의 호출에 의해 출력 결과가 달라질 수 있다.





  if ( tcgetattr(ttyfd, &orig_termios) < 0 )

    perror("can't get tty settings");


 함수 : int tcgetattr(int filedes, struct termios *termios_p)

이 함수는 파일기술자 filedes와 연관된 터미널 디바이스의 속성을 시험하는데 사용된다. 그 속성은 구조체 termios_p가 가리키는 곳으로 반환된다.
만일 성공하면, tcgetattr 은 0을 반환하고, 실패하면 -1을 반환한다.  
다음의 errno는 이 함수를 위해 정의된 에러상황이다.
EBADF : filedes 인수가 유용한 파일기술자가 아니다.
ENOTTY : filedes 가 터미널과 연관이 없다.

if (tcgetattr (desc, &settings) < 0) {
perror ("error in tcgetattr");
return 0;
}




 atexit(tty_exit);



음과 같음 함수를 실행 한다.




tty_raw();










'CAT-Security > 미분류' 카테고리의 다른 글

[Secuinside2013] beist_attack_game_150  (0) 2014.05.02
gdb 명령어 요약집  (0) 2014.04.28
[Defcon 21 ctf] policebox  (0) 2014.04.08
Python 예외처리  (0) 2014.01.09
리버싱의 기초 정리  (0) 2013.07.23
MBR 덤프해서 16비트 어셈블리 코드로 보는방법  (0) 2013.07.22

댓글(0)

Python 예외처리

CAT-Security/미분류|2014.01.09 17:54

프로그램 실행에 있어 에러가 발생할 경우, 이에 대한 적절한 처리를 위해서 Python에서도 try, exception 구문을 통해서 예외처리를 수행할 수 있도록 지원하고 있다.

대표적인 예외처리 구문으로 '파일 불러 오기' 구문이 있다.

예를 들어 아래와 같이 존재하지 않는 파일을 불러올 경우 'IOError'가 발생함을 볼 수 있다. 


>>> open('FileName', 'r')
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'FileName'



위와 같이 파일 불러오기 구문의 경우 실제 프로그램에서 에러가 자주 발생할 수 있는 부분으로 예외처리가 필수적이다.

Python에서는 아래와 같이 try, except 구문을 이용하여 예외처리를 수행할 수 있다.


try:
    ...
except [발생에러 [, 에러메시지변수]]:
    ...

<Type 1>

try:
    ...
except:
    ...

<Type 2>

try:
    ...
except 발생에러:
    ...

<Type 3>

try:
    ...
except 발생에러 , 에러메시지변수:
    ...



  • <Type 1>은 에러 종류에 상관없이 에러가 발생하기만 하면 except문 다음의 문장을 수행

 

  • <Type 2>는 발생한 에러가 except 문에서 정해놓은 에러와 같을 때만 except 문 아래의 문장을 수행

 

  • <Type 3>는 Type 2에서 에러메시지를 담을 변수를 생성하게 하는 방법이다.




예외처리 구문을 포함한 파일 불러오기 예제

fileName = 'FileName' # 불러올 파일 이름
try:
    open(fileName, 'r') #  읽기 모드(r)로 파일을 불러온다.
except IOError, e:
    print e
    print 'There is no "%s" file % fileName

실행결과:
[Errno 2] No such file or directory: 'FileOpen'
There is no "FileOpen" file



※ 에러 발생시키기 (raise)

raise는 일부러 에러를 발생시키기 위해서 사용하는 명령어로 경우에 따라서 어떠한 프로그래밍을 강제하기 위해서 사용할 수 있다. 예를 들어 클래스를 만들고 이를 상속받는 클래스에서 메소드를 반드시 구현하게 만들기 위해서는 아래와 같이 부모 클래스에서 raise를 이용할 수 있다.


>>> class Parent:
...    def mustMake(self):
...        raise NotImplementedError

>>> a = Parent()
>>> a.mustMake()
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
TypeError: unbound method mustMake() must be called with Parent instance as first argument (got nothing instead)

올바른 사용을 위해서는 아래와 같이 추가로 상속받는 클래스를 만들고 메소드를 구현해야 한다.

class Parent:
    def mustMake(self):
        raise NotImplementedError
    
class Child(Parent):
    def mustMake(self):
        print "mustMake() is made by Child class"

a = Child()
a.mustMake()

실행결과:
mustMake() is made by Child class



※ The class hierarchy for built-in exceptions

아래는 Python 자체 exception을 위한 발생에러 구조도이다. (URL:http://docs.python.org/library/exceptions.html )














'CAT-Security > 미분류' 카테고리의 다른 글

gdb 명령어 요약집  (0) 2014.04.28
[Defcon 21 ctf] policebox  (0) 2014.04.08
Python 예외처리  (0) 2014.01.09
리버싱의 기초 정리  (0) 2013.07.23
MBR 덤프해서 16비트 어셈블리 코드로 보는방법  (0) 2013.07.22
MBR (Master Boot Record) 정리  (0) 2013.07.22

댓글(0)

리버싱의 기초 정리

CAT-Security/미분류|2013.07.23 23:13

  지금부터 이루어지는 포스팅은  IA-32 Processor Architecture 기반입니다.

 

1.레지스터 - CPU 내부에 있는 8,16,32Bit 고속 저장소를 말하며 일반적으로 사용하고 있는

                 메모리 보다 데이터를 훨씬 빨리 Read ,Write 할 수 있음.

 

범용 레지스터 (General-Purpose Register) : 8

EAX, EBX, ECX, EDX, ESI, EDI레지스터는 우리 마음대로 쓸 수 있는 레지스터이다.

EAX : Accumulator Register. 곱셈나눗셈 명령에 쓰임.

EBX : Base Register.

ECX : Counter Register. 루프 카운터로 쓰임.

EDX : Data Register.

ESI : Source Index. 고속의 메모리 복사에 쓰임.

EDI : Destination Index. 고속의 메모리 복사에 쓰임.

 

ESP,EBP레지스터는 스택레지스터라고 불림.

ESP : Stack Pointer의 약자스택의 탑 가르킴.2개

EBP : Base Pointer. 고급 언어에서 사용하는 함수 파라미터와 지역변수를 가리키는 데 쓰일 것이

      다일반적인 산술이나 데이터 전송에 쓰여서는 안됨.

 

세그먼트 레지스터 (Segment Register) : 6

프로그램 수행에 필요한 내용들이 미리 메모리에 할당되어 있는 데 그곳의 주소를 갖고 있음.

-세그먼트 레지스터는 자세히 알 필요 없음

 

EIP Register = 명령 포인터 (Instruction Pointer) : 다음에 수행되어야 할 명령문의 주소

                    를 갖고 있게 된다. (우리가 흔히 알고 있는 PC=Program Counter와 같음.)

 

EFLAGS Register : EFLAGS의 각각의 비트는 1(set)이 되거나 0(clear)이 될 수 있

                      음예를 들어, Sign Flag라는 비트는 계산 결과가 음수인지 아 닌지를 표

                      현해줌.

                      즉이 레지스터를 통해 여러 가지 상태를 알 수 있다. (음수인 지 양수인

                      지오버플로우가 발생하였는지 등)

 

 

 

2.바이트 순서

-Little-Endian (리틀 인디언) : 주소의 낮은 자릿수를 기록하고주소값이 증가할수록 높은

                                   자릿수를 기록하는 것인텔 계열이 주로 사용

                                   Ex) 0x12345678 => 78 56 34 12

                                  

-Big Endian (빅 인디언) : 정수로 정렬된 큰 수에 대한 비교를 메모리의 작은 주소부터 큰 주

                             소 방향으로 읽으면서 바로 비교할 수 있어 더 빨리 할 수 있으며,

                             모든 정수와 문자열을 같은 순서 방향으로 읽을 수 있다는 장점 있

                             음.Motorola나 Sun, Sparc등 RISC에서 사용.

                             Ex) 0x12345678 => 12 34 56 78

 

 

 

3.Calling Conventions

-스택에 파라미터를 어떠한 순서로 넣을 것인가?

 전달되어진 파라미터를 어느 곳에서 해제할 것인가?

이 두가지에 따라 여러 가지 방식이 있는데 이를 콜링 컨벤션이라고 함.

 

_cdecl

파라미터 전달 방향오른쪽->왼쪽

파라미터 해제 호출한 쪽(Caller)

 

_stdcall

파라미터 전달 방향 오른쪽 ->왼쪽

파라미터 해제 호출 당항 쪽(Callee)

 

_fastcall

처음 두 개까지의 파라미터는 스택을 사용하지 않고 ECX와 EDX레지스터 사용.

파라미터 전달 방향 오른쪽->왼쪽

파라미터 해제 호출 당한 쪽(Callee)


명령어1

명령어2

설명

부등호 조건

Flag 조건

JA

JNBE

크면 분기

부호 없이 비교[unsigned] )

OP1>OP2면 분기

CF=0 & ZF=0

JAE

JNB

크거나 같으면 분기

부호 없이 비교[unsigned] )

OP1OP2면 분기

CF=0 | ZF=1

JB

JNAE

작으면 분기

부호 없이 비교[unsigned] )

OP1<OP2면 분기

CF=1

JBE

JNA

작거나 같으면 분기

부호 없이 비교[unsigned] )

OP1OP2면 분기

CF=1 | ZF=1

JG

JNLE

크면 분기

부호 있는 비교[signed] )

OP1>OP2면 분기

ZF=0&SF ==OF

JGE

JNL

크거나 같으면 분기

부호 있는 비교[signed] )

OP1OP2면 분기

SF==OF

JL

JNGE

작으면 분기

부호 있는 비교[signed] )

OP1<OP2면 분기

SF!=OF

JLE

JNG

작거나 같으면 분기

부호 있는 비교[signed] )

OP1OP2면 분기

ZF==1|SF!=OF

JE

 

같으면 분기

OP1=OP2면 분기

ZF==1

JNE

 

같지 않으면 분기

OP1OP2면 분기

ZF==0

JC

 

Carry Flag가 Set되면 분기

 

CF==1

JNC

 

Carry Flag가 해제되어 있으면 분기

 

CF==0

JO

 

Overflow가 Set되어 있으면 분기

 

OF==1

JNO

 

Overflow가 해제되어 있으면 분기

 

OF==0

JS

 

Sign Flag가 Set되어 있으면(음수이면분기

 

SF==1

JNS

 

Sign Flag가 해제되어 있으면(양수이면분기

 

SF==0

JZ

 

Zero Flag가 Set되어 있으면 분기

 

ZF==1

JNZ

 

Zero Flag가 해제되어 있으면 분기

 

ZF==0

JP

 

Parity Flag가 Set되어 있으면 분기

 

PF==1

JNP

 

Parity Flag가 해제되어 있으면 분기

 

PF==0


ADD oper1, oper2 - oper1에 oper2를 더한뒤 결과값을 oper1에 저장.

                   ex) add eax, 1000h   <-eax = eax+0x1000

 

SUB oper1, oper2 - oper1에서 oper2를 빼고 결과 값을 oper1에 저장.

                   ex) mov eax, 5

                       sub eax, 5   <-결과는 0이됨.

 

MUL / IMUL oper - MUL은 부호 없는 곱셈 명령을 수행.

                  IMUL은 부호 있는 곱셈 명령을 수행.

                  EAX에 저장되어진 값과 oper을 곱한 결과를 아래와 같이 저장한다.

                  - 8비트 연산은 AX에 저장

                    16비트 연산은 DX:AX에 저장

                    32비트 연산은 EDX:EAX에 저장

                  ->곱셈 결과가 두배가 되어 자리수를 넘어가기 때문에 곱셈을 하였을때 두배

                    크기의 공간에 저장됨. (자리수를 넘어가면 캐리 또는 오버플로우 발생.)

 

ADC oper1, oper2 - ADD와 유사하나 캐리 플래그가 이용됨.

                   oper1 = oper1 + (oper2 + 캐리 플래그)

                   캐리비트는 0으로 리셋됨.

                   ex) mov ebx, 5

                       mov eax, 0

                       stc   <-CF=1(캐리 플래그)

                       sbb ebx, eax   <-ebx=4

          

SBB oper1, oper2 - SUB와 유사하나 캐리플래그가 이용됨.

                   oper1 = oper1 - (oper2 + 캐리 플래그)

                   연산이 끝나면 캐리비트는 0으로 리셋됨.

 

INC oper - Increment

           oper의 값이 1만큼 증가.

           ex) mov eax, 1

               inc eax   <-eax의 값이 2로 값이 증가.

 

DEC oper - Decrement

           oper의 값이 1만큼 감소.

           ex) mov eax, 1

               dec eax   <-eax의 값이 0으로 감소.

 

STD - Set Direction.

      DF를 1로 설정.

 

CLD - Clear Direction.

      DF를 0으로 설정.

 

CMC - Complement Carry

      캐리 플래그를 반전시킨다.

      1이면 0, 0이면 1로 만든다.

 

STC - Set Carry

      캐리 플래그를 1로 만든다.

 

CLC - Clear Carry

      캐리 플래그를 0으로 만든다.



출처- http://blog.naver.com/coool219?Redirect=Log&logNo=60114153387

[출처] 리버싱 기초 1 |작성자 초딩코딩


'CAT-Security > 미분류' 카테고리의 다른 글

[Defcon 21 ctf] policebox  (0) 2014.04.08
Python 예외처리  (0) 2014.01.09
리버싱의 기초 정리  (0) 2013.07.23
MBR 덤프해서 16비트 어셈블리 코드로 보는방법  (0) 2013.07.22
MBR (Master Boot Record) 정리  (0) 2013.07.22
ASProtect 2.1 MUP 정리  (1) 2013.06.18

댓글(0)

MBR 덤프해서 16비트 어셈블리 코드로 보는방법

CAT-Security/미분류|2013.07.22 13:09

MBR 덤프해서 ASSEMBLY 코드로 보는방법


1. HxD 다운 / NASM 다운

HxD

NASM

2. HxD로 MBR Binary 덤프
HxD 설치 후 DISK 아이콘 선택
1440
디스크 중에서 물리 디스크 - MBR 분석할 물리 디스크를 선택 후 수락
1440
읽어보면 0000:0000부터 섹터 0만큼(512BYTE)가 MBR 영역이므로 해당 영역만 복사해서 새 파일로 만듬.
1440
새 파일 - 붙여넣기로 512바이트 영역 생성
1440
다른 이름으로 저장 - mbr.bin
1440
설치된 nasm 폴더내의 ndisasm.exe로 바이너리 이미지를 16비트 어셈블리로 변경
ndisasm.exe -b16(16비트 어셈블리) -o7c00h(base index지정) -a -s7c3eh mbr.bin > mbr.asm
680
나온 어셈블리 파일을 확인


'CAT-Security > 미분류' 카테고리의 다른 글

Python 예외처리  (0) 2014.01.09
리버싱의 기초 정리  (0) 2013.07.23
MBR 덤프해서 16비트 어셈블리 코드로 보는방법  (0) 2013.07.22
MBR (Master Boot Record) 정리  (0) 2013.07.22
ASProtect 2.1 MUP 정리  (1) 2013.06.18
AsPack MUP 정리  (2) 2013.04.05

댓글(0)

MBR (Master Boot Record) 정리

CAT-Security/미분류|2013.07.22 02:05

 

 
운영체제가 부팅될 때 POST(Power On Self-Test) 과정을 마친 후 저장매체의 첫 번째 섹터를 호출되는데 이때 해당 부트 코드가 수행된다. 부트 코드의 주 역할은 파티션 테이블에서 부팅 가능한 파티션을 찾아 해당 파티션의 부트 섹터(boot sector)를 호출해주는 역할을 한다. 만약, 부팅 가능한 파티션이 없을 경우에는 미리 정의된 에러 메시지를 출력한다.

다음 표는 MBR 각 영역에 대한 세부적인 데이터구조를 나타낸다.

범위 (Byte Range) 설명 (Decription)크기 (Size)
10 진수16 진수
 0 – 445 0×0000 – 0x01BD Boot code 446 bytes
 446 – 461 0x01BE – 0x01CD Partition table entry #1 16 bytes
 462 – 477 0x01CE - 0x01DD Partition table entry #2 16 bytes
 478 – 493 0x01DE – 0x01ED Partition table entry #3 16 bytes
 494 – 509 0x01EE – 0x01FD Partition table entry #4 16 bytes
 510 – 511 0x01FE – 0x01FF Signature (0x55AA) 2 bytes

 
파티션 테이블은 각각 16 바이트씩 4개의 엔트리를 가지고 있다. 따라서 이러한 구조만 가진다면 하나의 볼륨(MBR을 갖는 볼륨)에서 파티션은 4개 밖에 생성할 수 없을 것이다. 과연 그럴까?

부팅 가능한 주 파티션을 생성한다면 4개 밖에 생성할 수 없다. 따라서, 멀티부팅을 할 경우 총 4개까지 운영체제를 설치 할 수 있을 것이다. 다만, 별도의 프로그램을 통해 MBR 영역이 아닌 볼륨의 다른 영역에 주 파티션 정보를 기록하여 연결해주는 경우도 있지만 사용해본 결과 별로 권하고 싶지는 않다.주 파티션이 아닌 데이터 저장을 위한 논리 파티션은 4개 이상 생성하는 것이 가능하다. 이는 다음 포스팅에서 자세히 살펴볼 것이다.

다음은 16 바이트의 파티션 테이블 엔트리의 세부적인 데이터구조이다.

범위 (Byte Range) 설명 (Decription)크기 (Size)
10 진수16 진수
 0 – 0 0×0000 – 0×0000 Boot Indicator

00 = do not use for booting

80 = system partition

 1 byte
 1 – 3 0×0001 – 0×0003 Starting CHS address 3 bytes
 4 – 4 0×0004 - 0×0004 Partition type 1 byte
 5 – 7 0×0005 – 0×0007 Ending CHS address 3 bytes
 8 – 11 0×0008 – 0x000B Starting LBA address 4 bytes
 12 – 15 0x000C – 0x000F Total sectors 4 bytes

 
부트 지시자(boot indecator)는 해당 파티션이 부탕 가능한 파티션인지를 나타낸다. 0×80 값을 가질 경우 부팅 가능한 파티션을 의미하고, 0×00 값을 가질 경우 부팅이 가능하지 않은 파티션을 나타낸다. 그리고 CHS 주소 값이 나오는데 현재는 거의 대부분 LBA 모드를 사용하므로 사용되지 않고 있다. 그리고 해당 파티션의 시작 위치를 가르키는 LBA 주소 값과 파티션 전체의 섹터 수가 나온다. CHS와 다르게 LBA 주소의 마지막을 표시하지 않는 이유는 시작 LBA 주소에 섹터의 크기를 더하면  마지막 주소를 알 수 있기 때문이다.

4번째 바이트는 해당 파티션의 타입을 나타낸다. 4번째 필드를 System ID와 Partition type으로 구분하는 경우도 있지만 여기서는 파티션 타입으로 모두 정의한다.

 16진수 설명 (Description)
 00h Empty
 01h DOS 12-bit FAT
 02h XENIX root file system
 03h XENIX /usr file system (obsolete)
 04h DOS 16-bit FAT (up to 32M)
 05h DOS 3.3+ extended partition
 06h DOS 3.31+ Large File System (16-bit FAT, over 32M)
 07h Advanced Unix
 07h exFAT
 07h OS/2 HPFS
 07h Windows NT NTFS
 08h OS/2 (v1.0-1.3 only)
 08h AIX bootable partition, SplitDrive
 08h Commodore Dos
 08h DELL partition spanning multiple drives
 09h AIX data partition
 0Ah OPUS
 0Ah Coherent swap partition
 0Ah OS/2 Boot Manager
 0Bh Windows 95 with 32-bit FAT
 0Ch Windows 95 with 32-bit FAT (using LBA-mode INT 13 extensions)
 0Eh VFAT logical-block-addressable VFAT (same as 06h but using LBA)
 0Fh Extended LBA partition (same as 05h but using LBA)
 10h OPUS
 11h FAT12 OS/2 Boot Manager hidden 12-bit FAT partition
 12h Compaq Diagnostics partition
 14h FAT16 OS/2 Boot Manager hidden sub-32M 16-bit FAT partition
 16h FAT16 OS/2 Boot Manager hidden over-32M 16-bit FAT partition
 17h OS/2 Boot Manager hidden HPFS partition
 17h hidden NTFS partition
 18h ASTSuspend AST special Windows swap file (“Zoro-Volt Suspend” partition)
 19h Willowtech Willowtech Photon coS
 1Bh Windows hidden Windows95 FAT32 partition
 1Ch Windows hidden Windows 95 FAT32 partition (LBA-mode)
 1Eh Windows hidden LBA VFAT partition
 20h Willowsoft Overture File System (OFS1)
 21h [reserved] officially listed as reserved
 21h FSo2
 23h [reserved] officially listed as reserved
 24h NEC MS-DOS 3.x
 26h [reserved] officially listed as reserved
 31h [reserved] officially listed as reserved
 33h [reserved] officially listed as reserved
 34h [reserved] officially listed as reserved
 36h [reserved] officially listed as reserved
 38h Theos
 3Ch PowerQuest PartitionMagic recovery partition
 40h VENIX 80286
 41h Personal RISC Boot
 41h PowerPC boot partition
 42h SFS(Secure File System) by Peter Gutmann
 45h EUMEL/Elan
 46h EUMEL/Elan
 47h EUMEL/Elan
 48h EUMEL/Elan
 4Fh Obron boot/data partition
 50h OnTrack Disk Manager, read-only partition
 51h OnTrack Disk Manager, read/write partition
 51h NOVELL
 52h CP/M
 52h Microport System V/386
 53h OnTrack Disk Manager, write-only partition
 54h OnTrack Disk Manager (DDO)
 55h EZ-Drive (see also INT 13/AH=FFh “EZ-Drive”)
 56h GoldenBow VFeature
 5Ch Priam EDISK
 61h SpeedStor
 63h Unix SysV/386, 386/ix
 63h Mach, MtXinu BSD 4.3 on Mach
 63h GNU-HURD
 64h Novell Netware 286
 64h SpeedStore
 65h Novell NetWare (3.11)
 67h Novell
 68h Novell
 69h Novell NSS Volume
 70h DiskSecure Multi-Boot
 71h [reserved] officially listed as reserved
 73h [reserved] officially listed as reserved
 74h [reserved] officially listed as reserved
 75h PC/IX
 76h [reserved] officially listed as reserved
 7Eh F.I.X
 80h Minix v1.1 – 1.4a
 81h Minix v1.4b+
 81h Linux
 81h Mitac Advanced Disk Manager
 82h Linux Swap partition
 82h Prime
 82h Solaris (Unix)
 83h Linux native file system (ex2fs/xiafs)
 84h DOS OS/2-renumbered type 04h partition (hiding DOS C: drive)
 85h Linux EXT
 86h FAT16 volume/stripe set (Windows NT)
 87h HPFS Fault-Tolerant mirrored partition
 87h NTFS volume/stripe set
 93h Amoeba file system
 94h Amoeba bad block table
 98h Datalight ROM-DOS SuperBoot
 99h Mylex EISA SCSI
 A0h Phoenix NoteBIOS Power Management “Save-to-Disk” partition
 A1h [reserved] officially listed as reserved
 A3h [reserved] officially listed as reserved
 A4h [reserved] officially listed as reserved
 A5h FreeBSD, BSD/386
 A6h OpenBSD
 A9h NetBSD
 B1h [reserved] officially listed as reserved
 B3h [reserved] officially listed as reserved
 B4h [reserved] officially listed as reserved
 B6h [reserved] officially listed as reserved
 B6h Windows NT mirror set (master), FAT16 file system
 B7h BSDI file system (secondarily swap)
 B7h Windows NT mirror set (master), NTFS file system
 B8h BSDI swap partition (secondarily file system)
 BEh Solaris boot partition
 C0h CTOS
 C0h DR-DOS/Novell DOS secured partition
 C1h DR-DOS6.0 LOGIN.EXE-secured 12-bit FAT partition
 C4h DR-DOS6.0 LOGIN.EXE-secured 16-bit FAT partition
 C6h DR-DOS6.0 LOGIN.EXE-secured 12-bit Huge partition
 C6h corrupted FAT16 volume/stripe set (Windows NT)
 C6h Windows NT mirror set (slave), FAT16 file system
 C7h Syurinx Boot
 C7h corrupted NTFS volume/stripe set
 C7h Windows NT mirror set (slave), NTFS file system
 CBh DR-DOS/OpenDOS secured FAT32
 CCh DR-DOS secured FAT32 (LBA)
 CEh DR-DOS secured FAT16 (LBA)
 D0h Multiuser DOS secured FAT12
 D1h Old Multiuser DOS secured FAT12
 D4h Old Multiuser DOS secured FAT16 (<=32M)
 D5h Old Multiuser DOS secured extended partition
 D6h Old Multiuser DOS secured FAT16 (>32M)
 D8h CP/M-86
 DBh Concurrent CP/M, Concurrent DOS
 DBh CTOS (Convergent Technologies OS)
 E1h SpeedStor 12-bit FAT extended partition
 E2h DOS read-only (Florian Painke’s XFDISK 1.0.4)
 E3h DOS read-only
 E3h Storage Dimensions
 E4h SpeedStor 16-bit FAT extended partition
 E5h [reserved] officially listed as reserved
 E6h [reserved] officially listed as reserved
 EBh BeOS BFS (BFS1)
 F1h Storage Dimensions
 F2h DOS 3.3+ secondary partition
 F3h [reserved] officially listed as reserved
 F4h SpeedStor
 F4h Storage Dimensions
 F5h Prologue
 F6h [reserved] officially listed as reserved
 FBh VMware partition
 FEh LANstep
 FEh IBM PS/2 IML (Initial Microcode Load) partition
 FFh Xenix bad block table
 FMh VMware raw partition

(http://www.datarecovery.com/hexcodes.asp)
 
다음은 실제 내 컴퓨터의 MBR영역이다.

가운데 파란색으로 표시된 영역이 부트 코드를 수행하면서 정상적이지 않은 동작이 발생할 경우 출력하는 3가지 종류의 에러 메시지들이다.

  • Invalid partition table
  • Error loading operating system
  • Missing operationg system

다음 초록색으로 표시된 부분은 파티션 테이블을 나타낸다. 현재 해당 볼륨에 두개의 파티션이 존재하며, 첫 번째 파티션은 부팅가능한 파티션임을 알 수 있다. 각 파티션의 용량을 계산하면 다음과 같다.

  • Partition #1 : Total Sectors (07 53 04 62) = 58 GB
  • Partition #2 : Total Sectors (15 C9 40 E0) = 174 GB

각 파티션의 타입과 파티션의 시작위치를 살펴보면 다음과 같다.

  • Partition #1 : Type (07h = Windows NT NTFS), Starting LBA addresses (00 00 00 3F)
  • Partition #2 : Type (05h = DOS extended partition), Starting LBA addresses (07 53 04 A1)

그리고 마지막으로 MBR의 시그니처 값인 0x55AA가 오는 것을 알 수 있다.
 
 
그렇다면 파란색과 초록색 사이의 부분은 어떤 역할을 하는 걸까?

결론은 OS 버전에 따라 추가적인 부트 코드와 에러 메시지 지정, 장치의 GUID 값을 저장하고 있다. Windows 2000 (with SP3) 의 경우 해당 영역에 “C:WINNT\System32dmadmin.exe” 파일을 호출하는 코드가 들어간다. 이외에도 각 OS 버전에 따라 추가적인 파일을 호출하는 구문이 들어간다. http://thestarman.narod.ru/asm/mbr/WTC.htm

그리고 추가적인 코드 외에도 기본으로 에러 메시지 지정 코드와 장치의 GUID 값을 저장한다. 위의 MBR 덤프를 살펴보면 오프셋 437 – 439 위치에 “2C 44 64″ 값이 오는 것을 알 수 있다. 이것은 부트 코드 수행도중 에러 발생 시 에러 메시지의 위치를 지정하기 위한 것이다. MBR 영역은 부팅과 함께 메모리의 0000:7C00 번지에 로드된 후 0000:0600 번지로 이동한다.

이동한 상태에서 각 값의 위치(“072C”, “0744″, “0763″)는 각 에러메시지의 위치를 나타낸다. 이것에 대한 적당한 용어가 없으므로 에러 메시지 네비게이터(Error Message Navigator)라고 하자.

0000:072C : “Invalid partition table”
0000:0744 : “Error loading operating system”
0000:0763 : “Missing operating system”

하지만 이 값은 Windows 영문버전에서만 적용된다. 다음과 같이 독일어 버전에서는 오류메시지의 길이의 변화로 인해 값이 다르다. 그렇다면 한국어 버전에서는 왜 영어가 출력될까? 한글은 2 바이트를 쓰기 때문에 16 비트의 BIOS 상에서 해당 오류메시지를 출력하려면 기존에 설계된 코드 외에 추가적으로 많은 수정이 필요하기 때문일 것이다.

(http://thestarman.narod.ru/asm/mbr/Win2kmbr.htm)

그리고 에러 메시지 네이게이터 다음에 오는 4 바이트 (오프셋 440 – 443)은 마운트된 장치의 GUID 값으로 사용된다. MBR GUID에 대해서는 이전 글(Mounted Devices GUID Analysis)을 참조하자.

Tagged with: 





'CAT-Security > 미분류' 카테고리의 다른 글

리버싱의 기초 정리  (0) 2013.07.23
MBR 덤프해서 16비트 어셈블리 코드로 보는방법  (0) 2013.07.22
MBR (Master Boot Record) 정리  (0) 2013.07.22
ASProtect 2.1 MUP 정리  (1) 2013.06.18
AsPack MUP 정리  (2) 2013.04.05
[api]모달과 모달리스의 차이  (0) 2013.03.25

댓글(0)

ASProtect 2.1 MUP 정리

CAT-Security/미분류|2013.06.18 18:56


AsProtect MUP by Lazly.pdf


문서 파일 입니다.

잘못 된 점은 리플로 남겨주시면 감사하겠습니다.

'CAT-Security > 미분류' 카테고리의 다른 글

MBR 덤프해서 16비트 어셈블리 코드로 보는방법  (0) 2013.07.22
MBR (Master Boot Record) 정리  (0) 2013.07.22
ASProtect 2.1 MUP 정리  (1) 2013.06.18
AsPack MUP 정리  (2) 2013.04.05
[api]모달과 모달리스의 차이  (0) 2013.03.25
Callback(콜백 함수) 정리  (0) 2013.01.17

댓글(1)

AsPack MUP 정리

CAT-Security/미분류|2013.04.05 21:47


패커와 프로텍터의 차이점

 

패커

패커란 실행 파일 압축기를 말 한다. 정확한 명칭은 Run_Time 패커라고 한다. ‘실행 압축이란 실행 파일에 실행 코드를 원본 형태로 두지 않고 압축을 한 것 이다. 그리고 압축해제 코드를 실행 파일에 같이 넣어 놓은 것 이다. 그래서 프로그램이 실행 될 때 먼저 압축해제 코드를 만나 원본 실행 코드 압축이 풀린 뒤 실행이 된다. 이러한 실행 압축을 만드는 것을 패킹이라고 한다

패커의 사용 목적은 다음과 같다.


1.     실행 파일을 줄이고자 하는 목적

2.     PE 파일 내부의 코드와 소스를 감추기 위한 목적

 

 

프로텍터

프로텍터란 PE 파일(실행파일)을 리버싱으로부터 보호 하기 위한 프로그램 이다. 패커 처럼 실행 압축 할 뿐만 아니라 리버싱을 막기 위한 기법들이 추가 된다.

 

프로텍터의 사용 목적은 다음과 같다.

1.     크래킹 방지

2.     코드 및 리소스 방지

 

두 가지의 큰 차이점은 패커는 말 그대로 압축만을 할 뿐이고 프로텍터는 프로그램을 보호하기 위한 기법이 들어 간 것이다. 디버거를 종료 시킨다던지 불가능하게 한다 던지의 기법 등이 있다.


 

1.  PEID 확인


<PEID로 확인>


PEID Aspack으로 실행 압축 된 파일을 확인 해 봤을 때 이다. Aspack으로 실행 압축 되어있다라고 나오며 EP.aspack으로 시작 함을 알수 있다.

 


<메모리 주소 확인>


Aspack에서 맨 처음 살펴볼 두 곳 이다. 시작부분이 PUSHAD로 되어있어서 프로그램시작시의 레지스터들을 모두 스택에 저장 한다는 부분과 .Reloc .adata 사이에 .aspack이 위치 한다는 부분을 확인 할 수 있다. 주소값을 살펴보면은 .aspack의 주소값부터 시작됨을 확인 할 수 있다.

packing의 매커니즘은 간단하게 설명해서 압축 된 파일들을 해제하는 부분부터 시작하게 된다. .aspack의 주소부터 시작하는 이유는 압축 된 파일들을 해제 하기 위해서 이다. 압축 해제가 모두 되고 최종적으로 원래의 OEP로 가게 되어 실행 하게 되는 것 이다.

[압축해제루틴부터 시작] -> [압축해제 완료] -> [정상적인 프로그램 시작] 이 순인 것 이다.

즉 하드에서 존재하는 패킹된 파일의 크기가 1M가 이더라도, 압축이 풀려서 메모리에 올라 갈 때는 정상적인 크기로 올라가게 된다.



 

2.  Find OEP

<PUSHAD 후의 스택>


맨 처음에 있는 PUSHAD가 실행되고 난 이후의 레지스터와 스택 이다. 여기서 중요한 부분은 ESP 이다. 패킹이 모두 풀리고 난 후에 정상적으로 실행 될 레지스터를 저장 했기 때문에 패킹이 모두 끝나고 POPAD라는 명령어로 레지스터를 돌려받게 된다. 그렇기 때문에 스택에 저장된 ESP에 브레이크 포인터를 걸어 놓는다면 패킹이 모두 풀리고 정상적인 프로그램 시작 전으로 갈 수 있게 된다.


 

 

<EBPbreak point>


다음과 같이 esp의 주소에 직접적으로 브레이크 포인트를 걸어준다.



<POPAD 이후>


이렇게 POPAD 이후로 바로 오게 된다. 이 부분이 바로 실행 압축된 모든 압축을 풀고 정상적인 OEP로 돌아 가기 전에 POPAD로 레지스터를 돌려 받는 부분이다. 이 다음의 RETN 부분부터가 실제 프로그램이 실행 되는 부분이다.



<실제 프로그램 OEP>


다음으로 넘어오게 된다면 코드가 제대로 보이지 않아서 이런 식으로 보이게 된다. 컨트롤+A를 눌러주면은 코드가 제대로 정렬하게 된다.



<실제 프로그램 OEP>


다음과 같이 온전히 패킹이 풀리게 되었다.



<Dump>


이 상태로 덤프를 해주면 된다. Ollydbg의 기본기능이 아니라 Plugins의 기능 중 하나이기 때문에 플러그인을 따로 설정 해주어야 한다.



<Dump OEP 설정>


덤프로 바꿔줄 때 중요한 부분은 바로 OEP를 바꿔주는 부분이다. Start address base point로 해주고, Entry Point를 프로그램의 시작주소 – Base Point로 해주어야 한다. 또한 Rebuild import의 경우 ollydbg IAT를 재 배치해주는 옵션인데 많이 안정화가 되었다고 하지만 다른 툴을 돌려 복구 하도록 해보겠다.

 

 

 

 

 

 

 

 

3.  MUP

[alal은 패킹파일, AlZip_은 덤프파일]


이렇게 덤프파일로 저장을 하게 되면은, 패킹이 풀린 이후로 저장이 되기 때문에 압축이 풀린다. 즉 파일의 크기가 늘어난 것을 볼 수 있다.

이렇게 덤프로 파일을 만들어줄경우 정상적인 PE파일이지 못한다. 그래서 위에 보는 바와 같이 에러를 내게 된다. IAT가 엉망이기 때문이다. IAT를 제대로 설정해줘야 한다. 그때 사용 하는 툴이 바로 Import REConstructor이다.



<Import REConstructor>


툴의 사용 방법은 다음과 같다.

1.     Pick DLL 옆에 있는 박스에 ollydbg로 실행한 패킹된 원본파일(디버깅중인)Attach를 해준다.

2.     빨간 풍선 1번의 OEP값을 덤프 파일의 Entry Point의 값으로 해 준다.

3.     그 뒤 빨간 풍선 2번을 눌러주면 자동으로 RVA Size를 설정 해 준다.

4.     그리고 빨간 풍선 3번을 눌러주면 자동으로 IAT를 검색해 준다.

5.     그리고 마지막으로 Fix Dump로 덤프 파일에 덮어쓰기를 해주면 된다.

이렇게 해주면 패킹된 파일의 있던 IAT들을 덤프파일에 덮어 쓰게 되고, 덤프파일은 정상적인 실행 프로그램으로 재 탄생 되게 된다.(언패킹완료)



<OEP 설정 후>


AutoSerch를 해주었을 때의 스크린샷 이다. 자동으로 RVA Size가 잡히는 것을 볼 수 있다.



<Import 된 함수들>


dll들과 그에 사용되는 함수들이 출력됨을 확인 할 수 있다.

 



<덤프파일에 덮어쓰기>


그 뒤 덤프파일에 덮어 쓰기 해주면 된다.



<정상실행 화면>


정상적으로 실행 됨을 확인 할 수 있다.

'CAT-Security > 미분류' 카테고리의 다른 글

MBR (Master Boot Record) 정리  (0) 2013.07.22
ASProtect 2.1 MUP 정리  (1) 2013.06.18
AsPack MUP 정리  (2) 2013.04.05
[api]모달과 모달리스의 차이  (0) 2013.03.25
Callback(콜백 함수) 정리  (0) 2013.01.17
Code injection (1) - Basic  (2) 2013.01.02

댓글(2)

[api]모달과 모달리스의 차이

CAT-Security/미분류|2013.03.25 10:33



윈도우의 Form(형식)과 dialog(대화상자)를 모달 혹은 모달리스로 표시할 수 있다.



모달


간단한 개념으로 모달 창이 열렸을 때는 기존에 있던 창을 사용하지 못하는 방식이다.

즉 제어권을 독점하게 되어 그 창이 종료하기전까지는 기존창을 작업 할 수 없는 방식이다.


중요한 메세지를 표시하는 다이얼로그는 거의 모달로 나타낸다. visual studio의 정보 대화 상자나, api의 messagebox는 사용 할 수있는 모달 형식의 한 예이다.




모달리스


모달과는 반대의 개념으로 창이 열리더라도 기존에 있던 창을 작업 할 수 있다.

모달리스는 사용자가 순서에 상관없이 접근이 가능 하기 떄문에 사용자의 동작에 관계 없이 응용 프로그램의 상태를 일관성 있게 유지해야한다. 즉 프로그래밍 하기 더 어렵다는 애기이다.


도구창은 종종 모달리스 형식으로 표시되며, visual studio의 편집 메뉴에서 사용 할 수있는 대화상자들이 모달리스의 예 이다.

모달리스 형식은 자주 사용하는 명령이다 정보를 표시하는데 사용 한다.



'CAT-Security > 미분류' 카테고리의 다른 글

ASProtect 2.1 MUP 정리  (1) 2013.06.18
AsPack MUP 정리  (2) 2013.04.05
[api]모달과 모달리스의 차이  (0) 2013.03.25
Callback(콜백 함수) 정리  (0) 2013.01.17
Code injection (1) - Basic  (2) 2013.01.02
Python으로 레이싱 갤러리 사진 긁어 오기  (0) 2012.12.20

댓글(0)

Callback(콜백 함수) 정리

CAT-Security/미분류|2013.01.17 21:53

정의 호출된 함수를 알려주어, 다른 프로그램 또는 다른 모듈에서 함수를 호출 하게 하는 방법 일반적으로 운영체제(OS)가 호출할 어플리케이션의 함수를 지정해 특정한 사건 또는 메시지가 발발 했을 때 호출되도록 지정 할 수 있다. 이런 함수를 콜백 함수라고 한다.

 

즉 사용자가 필요할 때 호출해서 쓰는 함수가 아닌 어떤 이벤트가 발생 했을 때 사용자에게 알려주는 역할을 하고 있다. 호출 되는 것 이다. 어떤 이벤트에 의해 해당 함수를 호출 하는 것 이다.

 

함수호출과 CallBack함수의 가장 큰 차이점은 제어권에 있다.

 

호출자가 -> 피호출자 호출 (일반적인 함수 흐름)

피호출자 -> 호출자 호출 (callback의 함수 흐름)

 

계속적으로 요청하는것과, 무슨일(이벤트)가 벌어졌을 때 요청되어지는것의 차이

마우스 클릭을 예로 들면은 왼쪽클릭을 했는지를 계속해서 확인하는 것(user 함수),

왼쪽 클릭이 되었을때 확인 되어지는것(callback 함수)

                                                                         Callback함수 사용방법

Dll에서 User Program의 함수를 쓰고 싶을 때 특정 파라메터를 가지고 User Program의 함수를 호출 하게 한다.

1.     Use Program 함수에서 함수1을 정의 한다.

2.     2 DLL에 있는 레지스터 콜백 함수에다가 이 함수의 인자를 넘겨주면은 callback이 등록된다.

3.     DLL함수에서는 전역변수 하나를 배정해서, 인자값을 포인터로 넣어 준다.

4.     그 뒤 callbackFunc를 실행하면 지정한 함수가 실행이 된다.




Callback함수의 인자값들은 훅 프로시저 마다 다르다.

훅 프로시저들은 글로벌과 로컬로 나뉘어지며, 둘다 가능한 것이 있고 아닌것들이 있다.



                                                       글로벌&로컬 가능                             글로벌만 가능

 

둘의 큰 차이점

글로벌 훅 : 글로벌 훅을 위해서는 훅 프로시저는 어플리케이션 영역이 아닌 DLL이 적재되는 영역에 있어야 한다.

로컬 훅 : 특정 프로세스만을 후킹하므로 어플리케이션 영역이든 DLL영역이든 별 상관이 없다.

 

 

 

 

 


 

출처 : Windows Message Hooking

http://blog.naver.com/i2proda?Redirect=Log&logNo=150019571374

'CAT-Security > 미분류' 카테고리의 다른 글

AsPack MUP 정리  (2) 2013.04.05
[api]모달과 모달리스의 차이  (0) 2013.03.25
Callback(콜백 함수) 정리  (0) 2013.01.17
Code injection (1) - Basic  (2) 2013.01.02
Python으로 레이싱 갤러리 사진 긁어 오기  (0) 2012.12.20
python 공부 자료  (0) 2012.12.20

댓글(0)

Code injection (1) - Basic

CAT-Security/미분류|2013.01.02 23:47

Code injection 이란 말그대로 code를 상대방 프로세스에 넣어 버리는 것 입니다.

Dll injection에서 한단계 복잡하게 된 기술로서 주로 악성코드, 바이러스, 쉘코드등에 사용 됩니다.

Dll은 백신에 탐지가 잘 되서, 좀더 복잡한 code injection을 많이 사용 합니다.

code injection은 dll inejction과 달리 완전한 형태의 pe이미지를 가지고 하는것 이 아닌

데이터와 코드만을 가지고 상대방 프로세스에 주입시킨후, 상대방 api주소를 구한뒤 원격으로 실행 시키는것이기 때문에 기법이 dll보다는 살짝 어렵다고 알려져 있습니다.

다른프로세스 메모리에 접근할 때 사용되는 api 입니다.

Openprocess

주입할 대상 process에 대한 핸들을 얻는다.

VirtualAllocEx

대상 process 내의 메모리를 할당 한다.

WirteprocessMemory

할당된 메모리에 기록 한다.

CreateRemoteThread

대상 Process에 Thread를 생성 한다. LoadLibrary를 호출 합니다.

그림으로 표현하면 다음과 같습니다. 순서대로 1,2,3으로 진행 됩니다.

8.jpg

소스 분석

Main 소스 부분 입니다.

1.jpg

argv로 해당 프로세스의 PID를 얻어서 그것으로 InjectCode의 함수의 인자로 넣습니다.

이때의 해당 프로세스는 내것이 아닌 상대방 프로세스 입니다.

2.jpg

_THREAD_PARAM의 부분이 바로 인젝션의 스트링값이 저장될 공간 입니다.

LoadLibraryA(), GetProcAddress()

"user32.dll", "MessageBoxA"

"www.lapislazull.tistory.com", "lazull"

등을 가져와서 쓸수 있게 선언 하는 부분 입니다.

나머지 단순 C언어 문법 부분 입니다.

3.jpg

hMod 부분

pPram->pFunc[0] -> kernel32!LoadLibraryA()

pParam->szBuf[0] -> "user32.dll"

LoadLibrary("user32.dll") 이 만들어 지는 부분 입니다.


pFunc 부분

pPram -> pFunc[1] -> Kernel32!GetProcAddress()

pParam->szBuf[1] -> "MessageBoxA"

GetprocAddress("MessageBoxA")이 만들어 지는 부분 입니다.


그리고 마지막 코드는

pFunc(NULL, www.lapislazull.tistory.com, "lazull", MB_OK) 부분 입니다.


ThreadProc 함수의 전체 코드는 다음과 같습니다.

hMod = LoadLibrary("user32.dll");

pFunc = GetprocAddress("MessageBoxA");

pFunc(NULL, www.lapislazull.tistory.com, "lazull", MB_OK);

이 함수 코드의 개념이 중요 합니다.


Code Injection 기법의 핵심은 독립 실행 코드를 인젝션 하는 것 입니다.

그러기 위해서는 코드와, 데이터를 같이 인젝션을 시켜야 합니다.

그리고 인젝션 하는 코드는 데이터를 정확히 참조 할 수 있어야 합니다.

위 함수의 경우 직접 API를 호출하지않고 문자열도 직접 정의해서 사용하지않습니다.

그저 넘어온 인자인 THREAD_PARAM 구조체에서 가져다 사용 하고 있습니다.

4.jpg


일반적인 프로그램의 소스의 경우 바로 이렇게 됩니다.

코드인젝션의 코드를 다른프로세스에 그대로 인젝션 한다면 정상적으로 실행되지 않습니다.

그 이유는 코드에서 사용되는 주소의 내용이 상대방 프로세스에 없기 때문 입니다.

따라서 주소에 해당하는 문자열과 API주소를 같이 인젝션 해야 합니다.(그래서 위와같은 코드를 쓰는것)

그 뒤 인젝션된 코드에서 데이터의 주소를 정확히 참조하도록 프로그래밍 되어야 합니다.

이와 같은 조건을 만족하기 위해서 해당 함수안에 있는 dll의 주소를 가져와 mesaages함수의 주소를 구하고 넣은 문자열등을 인자값으로 받아와서 호출하게 하는 것 입니다.

LoadLibraryA()와 GetprocAddress()만 있으면 모든 라이브러리 함수를 호출 할 수 있습니다.

이유는 대부분의 유저모드 프로세스는 kernel32.dll을 로딩하므로 LoadLibraryA(), GetProcAddress()의 주소를 직접 넘기는 것은 크게 무리가 없습니다. 다만 저 dll을 로딩하지 안흔 프로세스도 있긴 합니다.

OS가 달라지면 같은 모듈이라도 주소가 달라지게 됩니다.


5.jpg

6.jpg

7.jpg

전체적인 구조

OpenProcess()

// data : THREAD_PARAM

VirtualAllocEx()

WriteProcessMemory()

//code :ThreadProc()

VirtualAllocEx()

WriteprocessMemory()

createRemoteThread()

이와 같습니다.

상대방 프로세스에 data와 code를 각각 메모리 할당하고 인젝션 해주는것 입니다.

그리고 마지막으로 CreateRemoteThread() API를 이용해서 원격 스레드를 실행 시키는 것 입니다.

'CAT-Security > 미분류' 카테고리의 다른 글

[api]모달과 모달리스의 차이  (0) 2013.03.25
Callback(콜백 함수) 정리  (0) 2013.01.17
Code injection (1) - Basic  (2) 2013.01.02
Python으로 레이싱 갤러리 사진 긁어 오기  (0) 2012.12.20
python 공부 자료  (0) 2012.12.20
kernel object 와 handle 정리  (2) 2012.11.29

댓글(2)

Python으로 레이싱 갤러리 사진 긁어 오기

CAT-Security/미분류|2012.12.20 20:25


http://jangc.tistory.com/17

장모님 블로그를 보고 공부한것을 새로이 포스팅한 글입니다.



>>> racingGirlUrl = http://gall.dcinside.com/list.php?id=racinggirl&no=


변수로 racingGirlUrl에 dcinside의 url주소를 가져 옵니다.

파이썬에서는 ' 와 "의 묶음은 차이가 없습니다.



>>> for no in range(170710, 170720):
>>>     print racingGirlUrl + str(no)


그 뒤에 for문을 이용해서 racinggirl&no=뒤에 넣을 숫자들을 돌립니다.

그리고 print racingGrilUrl을 해주게 되면 결과값으로


http://gall.dcinside.com/list.php?id=racinggirl&no=222543

http://gall.dcinside.com/list.php?id=racinggirl&no=222544

http://gall.dcinside.com/list.php?id=racinggirl&no=222545

http://gall.dcinside.com/list.php?id=racinggirl&no=222546

http://gall.dcinside.com/list.php?id=racinggirl&no=222547

http://gall.dcinside.com/list.php?id=racinggirl&no=222548


이런식으로 쭉 뜨게 됩니다.

이 값을 url이라는 변수에 넣어 주도록 합니다.



>>>     url = racingGirlUrl + str(no)
>>>     f = urllib.urlopen(url)

url이라는 변수에는 갤러리의 주소값이 들어가고, 그 주소값을 urllib.urlopen()이라는 함수를 써서 f라는 변수에 넣습니다.

urllib의 모듈은 웹상의 문서나 파일을 가져올 수 있는 모듈입니다.  url이나 header등의 정보들을 가져 올 수 있습니다.


사용법은 아래와 같습니다.


print f.headers

print f.url



>>>     html = f.read()
>>>     imageUrlList = re.findall("http://image.dcinside.com/download.php[^']+", html)


저런식으로 변수에 넣어서, f.read()등으로 쓰이게 됩니다. url의 값을 읽은뒤 f.read로 소스값을 html이란 변수로 넣습니다.

print html을 하게 되면 페이지의 소스값이 출력되게 됩니다.


그 출력된 값을 re.findall 이라는 모듈을 사용하여서 또 다른 변수 imageUrlList에 넣습니다.

findall 이란, 첫번째 값과 두번째 값을 비교하는 모듈 입니다. 정규표현식을 써서 download.php뒤 에 있는 [^'] 이 부분과

html에(소스값들이 들어가있는)을 비교해서 같은부분을 찾는 것 입니다.


즉 html 안에 있는 download.php---블라블라 하는것들이(즉 .jpg파일) 걸러지게 되어서 imageUrlList에 들어가게 됩니다.

이렇게 넣은 imageUrlList가지고 또 하나의 for문을 돌립니다.


파일값을 가지고 왔으니 이것을 jpg로 변환시켜서 저장시키면 될 것 같습니다.



        for url in imageUrlList:
                print fileNo
                contents = urllib.urlopen(url).read()
                file(str(fileNo)+'.jpg', 'wb').write(contents)
                fileNo = fileNo + 1



imageUrlList로 받은 검색된 값을, url 만큼 돌려서 그것들을 0.jpg부터 해서 저장 하는 부분 입니다.

그렇게 되면 url에는 imageUrlList에서 뽑은 리스트의 값들이 각각 들어가게 되고 그것으로 file을 생성 할 수 있습니다.




추가적으로 ("http://image.dcinside.com/download.php) 이 주소가 아닌

                ("http://dcimg1.dcinside.com/viewimage.php 이 주소로 바뀐 것 같습니다.


원래 주소로 다운 받으려고 하면은, 빈 페이지가 나오고 저 페이지로 가야 정상적으로 다운이 됩니다.




완성 소스 입니다.



 #!/usr/bin/python

import urllib

import re

import urllib2



fileNo = 0

racingGirlUrl = 'http://gall.dcinside.com/list.php?id=racinggirl&no='

for no in range(222548, 222550):

        url = racingGirlUrl + str(no)

        html = urllib.urlopen(url).read()

        imageUrlList = re.findall("http://dcimg1.dcinside.com/viewimage.php[^']+", html)

#       print imageUrlList

        for url in imageUrlList:

#               print fileNo

                print url

                contents = urllib.urlopen(url).read()          #소스값을 가지고 옴

                file(str(fileNo)+'.jpg', 'wb').write(contents)

                fileNo = fileNo + 1








'CAT-Security > 미분류' 카테고리의 다른 글

Callback(콜백 함수) 정리  (0) 2013.01.17
Code injection (1) - Basic  (2) 2013.01.02
Python으로 레이싱 갤러리 사진 긁어 오기  (0) 2012.12.20
python 공부 자료  (0) 2012.12.20
kernel object 와 handle 정리  (2) 2012.11.29
[시스템 기초] 스터디(3주차)  (0) 2012.11.27

댓글(0)