태터데스크 관리자

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

태터데스크 메시지

저장하였습니다.

[윈도우 후킹] 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)