태터데스크 관리자

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

태터데스크 메시지

저장하였습니다.

kernel object 와 handle 정리

CAT-Security/미분류|2012.11.29 14:49

  • 쓰레드의 경우 쓰레드에 대한 기본 정보가 커널 오브젝트에 생성됩니다.
    커널 오브젝트 핸들은 프로세스에서 커널 오브젝트에 접근하기 위한 키 같은 녀석이구요.

    프로세스는 커널 오브젝트 핸들 테이블(핸들값과 커널 오브젝트의 실 주소값의 매핑 테이블)을 통해
    커널 오브젝트에 접근하게 됩니다.

    다시 말하지만, 커널 오브젝트는 해당 오브젝트의 기본 정보를 담고 있습니다.
    쓰레드의 경우, 쓰레드의 서스펜드 카운트, 컨텍스트 정보등이 포함되어 있습니다.

    결론부터 말씀드리면, 쓰레드의 커널 오브젝트는 하나입니다.
    여러 방법을 통해 커널 오브젝트는 공유할 수 있는데....
    1. 자식 프로세스에게 상속
    2. Named (쓰레드의 경우 Named가 없죠)
    3. DuplicateHandle

    이렇게 여러 프로세스가 하나의 커널 오브젝트를 각기 다른 핸들값으로 공유할 수 있습니다.
    즉, 커널 오브젝트는 1, 오브젝트 핸들은 n이 될 수 있습니다.






http://sweeper.egloos.com/2814944


http://www.viper.pe.kr/wiki2/wiki.php/%C1%A4%B8%AE/KernelObjects


http://firepig.tistory.com/13



http://www.google.co.kr/#hl=ko&newwindow=1&tbo=d&sclient=psy-ab&q=handle%EA%B3%BC+kernelonject&oq=handle%EA%B3%BC+kernelonject&gs_l=hp.3...527157.538481.4.538650.30.27.3.0.0.2.317.5018.0j23j3j1.27.0.crnk_timediscountb..0.0...1c.1j4.ESJNtq7wL6k&pbx=1&bav=on.2,or.r_gc.r_pw.r_qf.&fp=df37d557c318de02&bpcl=39314241&biw=1280&bih=890



댓글(2)

[시스템 기초] 스터디(3주차)

CAT-Security/미분류|2012.11.27 22:46


파일 리스트와 파일 속성

리눅스에서 ls- al을 했을경우 나타나는 파일정보를 상세히 설명한 그림 입니다.

맨 앞에 -은 파일유형으로 보통 디렉토리의경우 d의 값을 가직 ㅗ있습니다.

파일 허가권은 [3-3-3] 식으로 rwx의 값들을 가지고 있는데, 각각이 소유자 그룹 다른사용자의 권한 설정을 가지고 있습니다.

링크수는 말그대로 하드,소프트 링크가 걸려있는 수를 말해 줍니다.

파일 소유자의 이름과 그룹이름은 따로 설명이 필요 없을 것 같습니다.

파일크기는 byte로 나타나며, 마지막 변경 날짜/시간이 그 뒤에 나오고, 마지막으로 파일이름이 있습니다.





파일허가권을 상세히 설명한 그림 입니다. 위에 [3-3-3]이라고 설명 해드렸는데, 더 자세히 설명해 드리도록 하겠습니다.

r -> 읽기권한    4 (2의2승)

w - > 쓰기권한 2 (2의1승)

x -> 실행권한   1 (2의0승)

총 이 세가지의 권한을 가지고 있으며, 총 더한 값은 7입니다.


이 권한을 설정하는 명령어로는 chmod가 있으며, 명령어 사용방법은 chmod 755 파일이름 이런식의 순을 가지고 있습니다.

소유자에게 읽기권한과 실행권한만을, 그리고 나머지는 아무권한도 주지 않을 경우에는

4+1 = 5 

0    = 0

0    = 0

으로 chmod 500 파일이름 이런식으로 권한을 줄 수 있습니다.




명령어 실행절차

일반적으로 시스템사용자가 명령어를 실행시켰을 때 명령어를 찾아서 실행시키는 경로와 절차는 다음과 같습니다.
현재 작업디렉토리에서 찾음.
$PATH에서 찾음
찾은후에 실행권한 체크
권한이 있다면 실행시킨 사용자의 UID로 실행
권한이없다면 이 파일이 Setuid bit가 있는가를 확인

Setuid bit가 있다면 명령어 소유주의 UID(Effective UID)로 실행





setuid가 걸려있는 passwd 프로그램의 흐름도 입니다.

일반 계정으로 passwd를 실행하면, 바로 권한이 전환되고 root 계정의 권환으로 프로그램이 돌아가게 됩니다.

프로그램이 정상 실행 된 뒤 프로그램이 종료되기 전에 권환을 전환해서 일반사용자의 권환으로 돌려주게 됩니다.


하지만 여기서 종료될때 권환전환이 되기전에 프로그램이 어떠한 공격을 받게되고, 그 상태에서 명령어해석기인 shell이 뜨게 된다면은

그 shell은 root 권환의 shell로 돌아가게 되게 됩니다. 즉 권환은 매우 조심스럽게 다뤄 져야 합니다.






위 프로그램은 단순히 빅엔디안방식인지, 리틀엔디안 방식인지 설명하기 위해 만든 프로그램 입니다.

리눅스는 리틀엔디안방식이기 떄문에 위에 0a 00 00 00 값으로 들어가게 됩니다.



리틀엔디안과 빅 엔디안 방식의 차이점입니다.


댓글(0)

리그 오브 레전드 첫 금장

CAT-Security/미분류|2012.11.24 15:38



ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

그냥 기분좋아섴ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

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

kernel object 와 handle 정리  (2) 2012.11.29
[시스템 기초] 스터디(3주차)  (0) 2012.11.27
리그 오브 레전드 첫 금장  (0) 2012.11.24
TCHAR, _tmain등 (SBCS, MBCS, WMCS)의 이해 및 정리  (1) 2012.11.22
[문제풀이] abexcm5 분석  (0) 2012.11.22
스터디 3주차  (0) 2012.11.18

댓글(0)

TCHAR, _tmain등 (SBCS, MBCS, WMCS)의 이해 및 정리

CAT-Security/미분류|2012.11.22 20:59

1. 문자셋의 종류와 특성

- 문자셋 (Character Sets) : 약속된 문자의 저장과 표현방법, 대표적으로 아스키코드와 유니코드가 있음.

- 아스키코드 (ASCII CODE) : 영어 및 확장문자 256개 표현. 1 바이트.

- 유니코드 (UNICODE) : 전 세계 모든 문자 표현. 65,536 개 표현가능. 2 바이트.


- 문자셋의 종류

1) SBCS (Single Byte Character Set)

- 문자 저장과 표현에 1 바이트만 사용. 아스키코드가 해당됨.

 

2) MBCS (Multe Byte Character Set)

- 문자 저장과 표현에 1 바이트 혹은 2 바이트를 사용.

- MBCS 는 SBCS 를 포함한다. 대부분의 문자들을 2 바이트로 처리하되, 경우에 따라서 1 바이트로 처리한다. 즉, 아스키코드에서 정의하는 문자들을 처리할 경우 1 바이트, 아스키코드에서 정의하지 않는 문자를 처리할 경우 2 바이트로 처리한다.

- 효율적이나 프로그램 구현에 있어 세심한 주의가 필요하다.

- 유니코드는 아님

 

3) WBCS (Wide Byte Character Set)

- 문자 저장과 표현에 2 바이트만 사용. 유니코드가 해당됨.

- 안정적이므로 많이 사용 됨







2. 자료형을 정의하는 이유

1. 선언의 편리성

긴문장 대신 간결하고 의미도 보다 강력하게 부여된 이름을 변수 선언시에 사용 한다.


2. 확장의 용이성

typedef unsigned char STR_LEN -> typedef unsigned int STR_LEN

(단 한번의 수정으로 STR_LEN 자료형을 쓰는 모든 변수를 캐릭터형에서 인트형으로 확장 시켰다.)






MBCS와 WBCS를 동시에 지원하기 위한 매크로

MBCS와 WBCS를 동시에 지원한다는 말은 곧, 아스키코드와 유니코드를 동시에 지원한다는 말과 일치한다고 봐도 된다.
Windows에서는 MBCS와 WBCS를 동시에 수용하는 형태의 프로그램 구현을 위해서 매크로를 정의하고 있다.

tchar.h의 일부를 보기 좋은 구조로 간략화 한 것

 #ifdef UNICODE
    typedef WCHAR     TCHAR;
    typedef LPWSTR    LPTSTR;
    typedef LPCWSTR  LPCTSTR;
#else
    typedef CHAR     TCHAR;
    typedef LPSTR    LPTSTR;
    typedef LPCSTR  LPCTSTR;

위 매크로가 어떻게 동작되는지 예를 들어 보자.
다음과 같이 선언된 배열이 있다.

TCHAR arr[10];

만약 UNICODE라는 매크로가 정의되어 있지 않으면, MBCS 기반, UNICODE라는 매크로가 정의되어 있으면, WBCS 기반의 문자열 저장이 가능하게 한다.


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

[시스템 기초] 스터디(3주차)  (0) 2012.11.27
리그 오브 레전드 첫 금장  (0) 2012.11.24
TCHAR, _tmain등 (SBCS, MBCS, WMCS)의 이해 및 정리  (1) 2012.11.22
[문제풀이] abexcm5 분석  (0) 2012.11.22
스터디 3주차  (0) 2012.11.18
아파치 설정법 모음  (0) 2012.11.13

댓글(1)

[문제풀이] abexcm5 분석

CAT-Security/미분류|2012.11.22 17:09

문제는 쉬운편이고, 단순히 점프문 수정이라든지 비교하는부분의 값들을 바꾸면 되는 문제입니다.

그래서 문제 자체의 풀이보다는 함수가 어떻게 흘러가고 호출되며 무슨일을 하는지에

초점을 맞춰서 공부 했습니다.

 

2.jpg

 

 

abexcm5의 실행 화면 입니다. 인증키를 요구하고 틀린지 맞는지를 확인 합니다.

 

1.jpg

Ctrl + N을 눌러서 abexcm5의 함수 목록을 확인 했습니다.

GetDlqItemTextA는 입력을 받는 함수이고

Istrcat은 C언어의 strcat의 함수와 비슷한 함수이고

Istrcmp는 C언어의 strcmp 함수와 비슷한 함수입니다. (이름 거의 똑같네요.....)

 

맨처음 GetModuleHandleA의 시작 주소를 구합니다.(DialogBoxParmA의 생성을 위해)

 

3.jpg

우선 DialogBoxParmA를 호출해서 사용자의 입력을 기다립니다.

그 뒤 사용자의 시리얼값을 입력 합니다. 사용자가 입력한 값이 저장됨을 확인 해씁니다.

 

4.jpg

 

그 뒤에 볼륨 인포메이션이라고하면서 뭔가의 값을 저장하는데 안쓰입니다.

5.jpg

 

그 뒤에 istrcat은 문자열을 이어주는 함수 입니다.

아무것도 없는 0040225C 공간에 4562-ABEX를 이어줘서 문자열 복사가 된것 처럼 되었습니다.

6.jpg

 

그 뒤 DL에 2의 값을 주고 4562 이 부분의 문자열들을 +1씩 해줍니다.

즉 5673이 되고, 6784가 되는것을 확인 할수 있었습니다.

7.jpg

 

그 뒤  L2C-5781이라는 문자열을 PUSH하고, 그 밑에 바뀌었지만은

00402000 이라는 공간에 L2C-5781을 저장 합니다.

그 뒤에 +2씩 해준값인 6784-ABEX를 PSUH하고 00402000곳에 붙여 버립니다.

그래서 L2C-5781784-ABEX가 완성 됩니다.

 

8.jpg

 

 

이 문자열을 사용자가 입력한 문자열과 비교 합니다.

 

9.jpg

 

00402000 이곳을 사용자가 입력한 부분으로 바꾸거나

00402324 이곳을 시리얼 부분으로 바꾸거나

점프문을 수정하거나

아예 처음부터 시리얼을 입력하면은 인증이 확인됨을 확인 했습니다.


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

리그 오브 레전드 첫 금장  (0) 2012.11.24
TCHAR, _tmain등 (SBCS, MBCS, WMCS)의 이해 및 정리  (1) 2012.11.22
[문제풀이] abexcm5 분석  (0) 2012.11.22
스터디 3주차  (0) 2012.11.18
아파치 설정법 모음  (0) 2012.11.13
sdfsdf  (0) 2012.11.13

댓글(0)

스터디 3주차

CAT-Security/미분류|2012.11.18 23:22

http://blog.naver.com/pk920207?Redirect=Log&logNo=110146983473

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

TCHAR, _tmain등 (SBCS, MBCS, WMCS)의 이해 및 정리  (1) 2012.11.22
[문제풀이] abexcm5 분석  (0) 2012.11.22
스터디 3주차  (0) 2012.11.18
아파치 설정법 모음  (0) 2012.11.13
sdfsdf  (0) 2012.11.13
리눅스 아파치 서버 설치  (0) 2012.11.13

댓글(0)

아파치 설정법 모음

CAT-Security/미분류|2012.11.13 16:03
not found 해결법
http://blog.naver.com/PostView.nhn?blogId=emtype&logNo=100156272283

우분투 apm 설정(아파치설치 등등)

http://www.cmsfactory.net/ubuntu-install-apache-php-mysql


고정 ip 설정

http://www.cmsfactory.net/ubuntu-network-static

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

[문제풀이] abexcm5 분석  (0) 2012.11.22
스터디 3주차  (0) 2012.11.18
아파치 설정법 모음  (0) 2012.11.13
sdfsdf  (0) 2012.11.13
리눅스 아파치 서버 설치  (0) 2012.11.13
[시스템 기초] 스터디(2주차)  (0) 2012.11.09

댓글(0)

sdfsdf

CAT-Security/미분류|2012.11.13 15:55

sdfsdf

libxml2-dev-linux-x86_64-2.6.27.tar.bz2


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

스터디 3주차  (0) 2012.11.18
아파치 설정법 모음  (0) 2012.11.13
sdfsdf  (0) 2012.11.13
리눅스 아파치 서버 설치  (0) 2012.11.13
[시스템 기초] 스터디(2주차)  (0) 2012.11.09
gdb 잘나와있음  (2) 2012.11.09

댓글(0)

리눅스 아파치 서버 설치

CAT-Security/미분류|2012.11.13 13:31

아파치 설치

1. http://blog.naver.com/feelwoo?Redirect=Log&logNo=100119454470


vmx설치

2.http://220.70.2.30/Common/Board/Files/2009_openwrt%20%EC%84%A4%EC%B9%98%EA%B0%80%EC%9D%B4%EB%93%9C(v2.0)_ASUS.pdf

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

아파치 설정법 모음  (0) 2012.11.13
sdfsdf  (0) 2012.11.13
리눅스 아파치 서버 설치  (0) 2012.11.13
[시스템 기초] 스터디(2주차)  (0) 2012.11.09
gdb 잘나와있음  (2) 2012.11.09
[시스템 기초] 스터디(1주차)  (0) 2012.11.08

댓글(0)

[시스템 기초] 스터디(2주차)

CAT-Security/미분류|2012.11.09 17:19


스택 부가 설명

-사진 출처-해커스쿨


스택에 대한 이해를 좀더 하기 위해 간단한 함수를 가져 왔습니다.

1주차때 스터디를 하신분들은 스택이 어떤식으로 쌓이는지 대략적으로 아시게 되셨을거라고 믿습니다.

허나 main()함수에서만 쌓이는 방법은 알고있지만,함수 인자 혹은 다른 함수의 지역변수는 어떻게 쌓이는지에 대해 궁금하실것 입니다.

이것을 설명하기 위한 예제 입니다.


프로그램의 실행 결과 모습 입니다.

메인함수 내에 있는 x와 y는 가장 오른쪽 스택에 자리잡힘을 알수 있고, 그 다음주소에 area의 주소가 잡힘을 알 수 있습니다.

시스템 스택은 cpu를 따라간다고했고, 현재 cpu는 32bit를 기준으로 하기에 모두 4바이트만큼의 크기를 가집니다.


인자 x와 y의 주소값 역시 약간 떨어진곳에 쌓이는것을 확인 할 수 있지만은 모양이 조금 다릅니다.

바로 x부터 쌓인것이 아니라 y부터 쌓인 것 입니다.


그리고 함수내의 지역변수 area의 경우 가장 마지막에 쌓인 것을 확인 할 수 있습니다.

이것을 그림으로 표현하면은 이런식으로 표현이 가능하게 됩니다.



순서 대로 쌓인 모습입니다.

4바이트씩 순서대로 쌓였는데, 함수의 인자모습은 약간 특이 함을 확인 할 수 있습니다.



위의 모습대로 바로 x 와 y가 거꾸로 쌓인것이 아니라 그대로 쌓인것이지요.





좀더 살펴보면은 함수인자가 쌓이고, 그 다음에 get_area 내의 area 변수가 쌓임을 알 수 있습니다.


즉 정리하자면

이런식으로 쌓이게 됨을 알 수 있습니다.



신기한것은 함수인자들과 Get_area()내의 area 함수 사이에 빈공간이 있습니다. 8바이트의 빈 공간이 있는데

이 빈공간에 쌓이는것들이 무엇일까요?






어셈블리의 이해


- 프로그램의 수행과정을 명확히 알 수 있다.
- 메모리에 대한 이해가 깊어진다
- 시스템에 대한 이해도 상승
- 프로그램의 최적화 및 리버스엔지니어링을 하기위해 필요하다.
- 고급 시스템 해킹(bof) 을 수행하기 위해 필요

 


cpu 레지스터

 

- 메인메모리, 시스템 메모리외에 cpu의 내부에는 레지스터라 불리는 특별한 메모리

- cpu가 접근할 수 있는 메모리중에서 가장 빠르게 동작하는 메모리

- cpu가 여러가지 연산등의 처리를 하는 동안 필요한 임시적인 데이터들을 보관하는데 사용된다.

 

EAX : 누산기(acumulator)레지스터라 불리며, 곱셈이나 나눗셈 연산에 사용

EBX : 베이스(BASE) 레지스터라 불리며, 메모리 주소 지정시에 사용

ECX : 계수기(counter)레지스터라 불린다. ex)loop, for...

EDX : 데이터(data)레지스터라 불리고, 곱셈 나눗셈에서 eax와 함께 쓰이며 부호확장 명령등에 사용

         32bit -> 2^32 - 42억   edxeax  부족한것을 edx가 앞에 붙어서 도와준다.

ESI : 다량의 메모리를 옮기거나 비교할 때 그 소스의 주소를 가진다.

EDI : 다량의 메모리를 옮기거나 비교할 때 그 목적지의 주소를 가진다.

ESP : 스택 포인터라고 불리고 스택의 가장 윗부분을 가리킨다.

EBP : ESP를 대신해서 스택에 저장된 함수의 파라미터나 지역변수의 주소를 가리키는 용도로 사용된다.

         상대주소를 기리킬때 유용하다.

EIP : 다음에 실행될 주소를 가리킨다.




CPU 레지스터중 꼭 확실히 짚고 넘어가야할 중요한 레지스터가 2개 있습니다. 바로 esp와 ebp 입니다.


ESP (Extended Stack Pointer)
현재 스택의 가장 위에 들어있는 데이터를 가리키고 있는 포인터
-  Intel CPU에서는 스택이 거꾸로(리틀엔디언자라므로 데이터가 하나 PUSH 될때마다 ESP 값은 감소

EBP (Extended Base Pointer)
- 현재 스택에 가장 바닥을 가리키는 포인터
- 새로운 함수가 호출될 때마다 EBP 레지스터 값이 지금까지 사용했던 스택 꼭대기의 위에 위치하게 되고 새로운 Stack이 시작
따라서 EBP는 새로운 함수가 호출이거나 현재 실행중인 함수가 종료되어 리턴될 때마다 값이 달라짐



 



단순한 구구단 프로그램을 디버그 프로그램인 gdb를 이용해서 디버깅 한것 입니다.

하나하나 상세하게 설명 하도록 하겠습니다.





맨처음 프로그램으로 ebp가 push되고(push %ebp), 그 다음 esp가 ebp의 주소로 잡히게 됩니다.(mov %esp, %ebp)

그 뒤에 8바이트를 esp에서 sub한다는 말은, 주소가 거꾸로 자라는거 다들 아시죠? 즉 8바이트만큼 esp를 뺴줘서 공간을 확보하겠다는거입니다.(sub $0x8, %esp)

그 뒤 and $0xffffffff0와 %esp와 mov 0x0, %eaxx 그리고 sub %eax, %esp는 의미없는 함수 프롤로그 부분 입니다.

여기까지가 함수의 프롤로그라고 불리는 녀석 입니다. 처음 프로그램을 형성할때 형성 되는 과정 입니다.




sub $0x4, %esp -> esp만큼을 4바이트 더 빼준다는 얘기는, 그림과 같이 4바이트만큼을 더 공간확보를 한다는 뜻입니다.

lea 0xfffffff8(%ebp), %eax -> ebp로부터 0x100-0xff = 8 만큼 떨어진곳에 있는 것의 주소값을 복사해서 eax에 넣는다는 뜻 입니다.

즉 8바이트로 선언된 곳에서의 주소값을 가져와서 eax에 넣는다는 뜻 입니다.

push%eax -> 가져온 주소값을 스택에 넣습니다 .esp는 4 만큼 더 커집니다.

leax 0xfffffffc%ebp), %eax -> 같은 방법으로 4만큼 떨어진곳에 있는 것의 주소값을 복사해서 eax에 넣는다는 뜻 입니다.

push%eax -> 가져온 주소값을 스택에 넣습니다 .esp는 4 만큼 더 커집니다.

push $0x8048494 -> x/s 0x8048494를 해보면 저기가 가르키고있는 값을 알 수 있습니다. %d %d가 들어가 있고esp는 4만큼 더 커집니다.

call 0x804827c(scanf) -> scanf함수를 불러오는 부분 입니다. 앞의 인자값들을 이용해서 sacnf 함수를 call 합니다.

add $0x10, %esp -> 잘 보시면은 처음 8바이트 선언된것 말고, 4바이트부터 push 0x8048494까지 총 16바이트를 씀을 알수있습니다

scanf함수를 쓰고, 쓴 만큼 메모리를 정리 해 주는 작업 입니다.






sub $0x8, %esp -> 8바이트만큼을 할당 해 줍니다.

pushl 0xfffffff8(%ebp) -> 위에 설명 했습니다.

psuhl 0xfffffffc(%ebp) -> 위에 설명 했습니다.

call 0x804839c <gugudan> -> gugudan 이라는 함수를 호출 합니다. 인자값은 %d %d scanf 한 값들 입니다.

그 뒤 add $0x10, %esp로 스택을 정리 해 줍니다.


leave

ret 

에필로그 부분 입니다.






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

sdfsdf  (0) 2012.11.13
리눅스 아파치 서버 설치  (0) 2012.11.13
[시스템 기초] 스터디(2주차)  (0) 2012.11.09
gdb 잘나와있음  (2) 2012.11.09
[시스템 기초] 스터디(1주차)  (0) 2012.11.08
[안티디버깅] UPX packer 이해  (0) 2012.11.08

댓글(0)

gdb 잘나와있음

CAT-Security/미분류|2012.11.09 17:06

http://blog.naver.com/mububja119?Redirect=Log&logNo=130119472091



고등학생분 사이트

http://iyounges.org/549

댓글(2)

[시스템 기초] 스터디(1주차)

CAT-Security/미분류|2012.11.08 14:06

본 글은 2학기 쥬니어 시스템 스터디 강좌 포스팅이며 쥬니어분들의 복습을 위해 작성 되었습니다.




1. 시스템은 어떻게 실행 될까?


우리가 마우스로 어떤 프로그램을 실행 시킬 때 그 명령을 수행하기 위해서 CPU에서 하드디스크의 자료를 가져옵니다.

불러온 자료를 연산후에 입출력 장치를 이용하여 그 결과를 화면에 뿌려 줍니다.

하지만 하드디스크는 CPU의 연산속도를 따라 올 수가 없습니다. 느린속도로 인해 효율성이 떨어 집니다.

이때 사용된 개념이 주기억장치(RAM)입니다. 휘발성데이터로 CPU와 하드디스크 사이에서 숨가뿌게 움직이게 됩니다.


이것이 바로 우리가 사용하는 폰노이만 구조 입니다.

이 방식은 크게 주기억장치(RAM)중앙처리장치(CPU), 그리고 입출력 장치 (IOP - Input Output Processor) 의 세 단계로 구분됩니다.

프로그램을 메모리에 적재시켜놓고 cpu는 순차적으로 메모리에서 명령어를 가져와 수행하며 결과를 입출력장치로 주거나 받습니다.

보조기억장치는 용량이 크나 처리속도와 접근성이 떨어지고 주기억장치는 처리속도가 빠르고 접근이 쉬우나 비싸기 때문에 두가지를 적절히 사용합니다. 보조기억장치에 저장되있는 프로그램을 사용하고 싶을 때는 이 프로그램을 주 메모리에 적재하여 사용 합니다.

프로그램을 다 사용하였다면 메모리에서 제거하여 다른 프로그램을 실행할 수 있도록 공간을 비워준다.




이 방식을 쓰면 좋은점이 무엇일까요?

1. 효율성이 올라간다.

CPU - 하드디스크의 방식에서 각 두 장치의 장점을 가지고있는 RAM이 연산의 효율을 높혀 줍니다.

2. 적재시킨 메모리는 cpu와 바로 연산이 가능하다.

예를들어서 컴퓨터를 키고, 맨 처음 실행시키는 프로그램(곰플레이어,익스플로러)등은 약간의 딜레이가 생깁니다.

하지만 두번째 실행시키게 되면은, 매우 빠른속도로 실행됨을 알 수 있습니다. 바로 하드디스크 -> 램 -> CPU로 연산되었던 작업이

램에 적재되어있는 데이터때문에 하드디스크->램의 작업이 생략되고 램 -> CPU의 연산으로 바로 되기 때문입니다.






2. 이렇게 중요한 메모리(RAM)은 어떤 구조로 돌아가게 될까요?


이것은 우리가 사용하는 컴퓨터의 CPU 비트수에 관련이 있습니다.

우리가 사용하는 컴퓨터 CPU는 32bit와 64bit가 있습니다. 

이 비트 수에 따라 CPU가 한번에 처리 할 수 있는 데이터가 달라지는것이고, 이 크기가 곧 우리가 접근할 수 있는 메모리의 크기가 됩니다.

리눅스의 환경은 보통 32bit로 되어있고, 우리 서버 역시 32bit로 되어있기에 이 스터디는 32bit 기준으로 설명해드리도록 하겠습니다.

비트라는것은 0 혹은 1로 표현 할 수 있는 단위를 의미하고, 

최소값은 00000000000000000000000000000000 최대값은 11111111111111111111111111111111 을 의미 합니다.

즉 10진수로는 4294967295이고, 16진수로 0xffffffff를 의미 합니다.


메모리의 가장 큰 주소가 0xffffffff인 이유가 여기에 있습니다.

이 이상은 직접 표현 할수도, 접근 할 수도, 읽을 수도, 쓸 수도 없습니다.

32bit CPU에서 4G 이상의 메모리를 인식 할 수 없는 이유 입니다. 


여기서 의문점이 생깁니다. 2G의 메모리라면은 메모리 크기가 달라질까요?

정답은 아닙니다.현대의 운영체제는 가상메모리라고 불리는 메모리 관리 방식을 사용 하고 있고, 이를 사용하여 실제로 가지고 있는 메모리보다 훨 씬 더 많이 사용이 가능합니다. - 가상메모리는 검색해보세요.




3. 메모리 지도를 그려 보자

그림출처 - 해커스쿨 bof강좌



우린 가장 낮은 주소는 0이고, 가장 큰 주소는 0xffffffff인것을 알고 있습니다.

그럼 프로그램이 실행될때 프로그램들이 메모리에 어떻게 적재되는지에 대해서 알아보도록 해봅시다.

프로그램을 사용하고 싶을 때는 이 프로그램을 주 메모리에 적재하여 사용 합니다. 라는 설명을 위에서 했습니다. 


가장 높은주소에는 커널이라는 녀석이 자리 잡습니다.


커널설명 시스템의 자원을 관리 모든 시스템이 원활하게 작동할수록 제어하는 소프트웨어 운영체제를 구성하고있는 핵심으로 DRAM에 상주하여 시스템 구동에 필요한 환경설정과 수행되는 프로그램의 스케쥴링하는 소프트웨어 이다.

인터럽트나 시스템호출에 의해 수행되며 인터페이스등 기본기능을 제공하는 핵심적인부분입니다.

커널기능에는 프로세서 관리, 메모리관리 ,파일시스템관리, 네트워크관리 ,디바이스관리가 있습니다.


쉽게 말해서 프로그램을 실행 시킬때 메모리에 적재를 누가시킬까요? 커널이 합니다.

메모리 관리 커널이하고, 프로세서 역시도 커널이 관리 합니다. 파일도 관리하고 네트워크도 관리합니다. 디바이스도 관리합니다.

전부 다 관리하지요. 운영체제 혹은 매니저라고 생각 하시는 편이 쉽습니다. 커널에 대해서는 추가적으로 검색을 꼭 해주세요.




커널이 약 1기가 정도를 잡아먹고, 남은 3G는 유저영역이라고 해서 실제 유저가 쓰는 영역을 뜻합니다.

또한 유저 영역에서도 또 여러부분으로 비슷한 성질을 가진녀석들을 효율적으로 나누어서 사용 됩니다.




코드영역 - 이곳은 CPU가 읽어 해석 할 수 있는 기계어들이 위치 하고 있습니다. 하나의 프로그램이 실행 되면 이 코드영역에 저장 된 기계어들이 순차적으로 읽혀 나가면서 실행이 되게 됩니다.


데이터영역 - 전역 변수 및, 정적 변수 그리고 각종 변수들이 실제로 위치 하는 메모리 영역 입니다. 변수들을 선언 할때 초기화 되었는지 안되었는지에 따라 위치하는 메모리 영역이 다릅니다. 아직까지는 이렇게 깊게 생각 할 필요는 없고, 변수들이 자리잡는곳이라고 기억하면 됩니다.


힙영역 - malloc() 동적 할당 메모리를 할당 받는 함수를 통해 설정된 영역 입니다.


스택영역 - 함수 호출에 관한 거의 모든 것들이 위치하게 되는 메모리 영역 입니다. 함수 인자, 리턴어드레스, 지역변수등이 자리잡고 쉘의 환경 변수 역시 이곳에 자리 잡습니다. 


이 메모리 지도중에 스택영역에 대해서 집중적으로 설명해드리도록 하겠습니다.



4. 스택영역

스택영역은 나중에 들어온 자료가 가장 먼저 나가기 때문에 LIFO(Last IN, First OUT) 우리말로는 후입선출형 구조라고 합니다

이처럼 스택은 기본적으로 PUSH POP이라는 두개의 명령으로만 데이터를 추가하거나 제거할수 있으며, 이때 PUSH 혹은 POP되는 데이터의 크기는 스택을 구현하는 프로그래머가 마음대로 정 할 수가 있습니다.

 

그리고 OS에 기본으로 구현되어있는 스택을 시스템 스택이라 합니다.

우리가 메모리 맵에서 본 스택이 바로 시스템 스택 입니다. 이 시스템 스택의 기본 데이터 크기는 CPU의 크기와 일치 합니다

즉 우리는 현재 32bit CPU를 기준으로하고 있기 때문에 시스템 스택 데이터의 기본크기는 32비트 4바이트인 것 입니다.

이 시스템 스택 안으로 함수와 관련된 각종 정보들이 PUSH되거나 POP 되는 것 입니다.




스택의 움직임을 설명한 그림 입니다. PUSH는 넣는것을 POP은 빼내는것을 의미하고, LIFO의 구조를 가지고 있음을 알 수 있습니다.



기본적인 스택의 설명이었고, 지금부터는 살짝 집중 하셔야 합니다.

스택은 거꾸로 자랍니다. 즉 높은주소에서 낮은 주소로 자리잡게 됩니다.


즉 그림으로 설명하게 되면 이렇게 됩니다.

힙은 위로 자라며, 스택은 아래로 자랍니다. (설명상 눕혀서 설명했고 앞으로의 설명은 이렇게 눕히는 방식으로 설명 합니다.

이렇게 되면은 장점이 2가지가 있습니다.



1. 스택에서 커널로 영역 침입이 불가능 하다.

커널은 시스템의 전반적인것을 구성하는 매우 중요한 요소 입니다. 즉 침범되서는 안되는 성역 이지요.

그렇기에 아예 메모리가 쌓이는 방향을 반대로해서 영영 만날 수 없게 하는 구조로 만들어 두었습니다.

이렇게 되면은 보안적인 측면에서 매우 좋아짐을 확인 할 수 있습니다.

2. 메모리를 효율적으로 사용 관리 가능 하다.

힙영역에서 스택영역으로 침범하게 되더라도 충분히 넓기에 사용이 좋고, 스택역시 반대로 마찬 가지 입니다.

이런식으로 메모리를 효율적으로 쓰게 되는것이 장점중에 하나가 됩니다.





예제소스 입니다.

스택이 쌓이는 방향과, 메모리가 어떻게 쓰이는지 확인 할 수 있는 좋은 소스 입니다. 물론 해커스쿨에서 퍼왔습니다.(출처표시)




위 프로그램의 경우 메모리는 그림과 같이 자리 잡게 됩니다.

스택의 특성상 atth가 먼저 자리잡고, 그 뒤에 캐릭터형 배열 passwd가 자리 잡습니다.

또한 gets함수로 passwd의 입력을 제한없이 받을 수 있어서 auth 데이터를 변조 할 수 있습니다.

그래서 인증에 성공한다라는 메세지를 띄울 수 있습니다.


이런식으로 버퍼를 넘치게 해서 하는 공격을 BOF공격이라고 합니다.(검색한번 해보세요~_~)





위에서 신나게 설명 했었던 것들을 한번에 보여주는 그림 입니다.

argv argc 모르겠죠? 스택포인터(SP) 모르겠죠? 검색 한번 해봐요. 모르는것은 꼭 검색해보는 습관을 들이도록 해요^^














댓글(0)

[안티디버깅] UPX packer 이해

CAT-Security/미분류|2012.11.08 13:27

실행압축

실행압축이란 실행가능 한 파일(PE파일)을 대상으로 파일 압축을 하지만, 파일 내에 압축해제 코드를 포함 하고 있어서 

실행되는 순간 메모리에서 압축을 해제시킨 후 실행을 시키는 기술

 

압축해제 루틴이 존재 하기 때문에, 메모리에서 압축을 해제 시킨 후 실행되는 것이 특징

 

사용목적으로는, 압축이기에 파일 자체의 크기를 줄이는 효과로 전송 및 보관에 용의 함을 얻기 위함이고 가장 큰 목적으로는 내부 코드와 리소스를 임의의 사용자가 보지 못하게 방해 하는 것 입니다.

즉 압축이 되어있기에 임의의 사용자가 보기에는 압축된 데이터는 알아보기 힘든 형태의 바이너리로 저장이 되어 있습니다.

 

이중 UPX 실행압축에 대해 알아 보도록 하겠습니다.


.

첫째 섹션인 UPX0 RawDataSize 0이기에 파일 내에 존재 하지 않습니다.

(RawDataSize는 파일에서 섹션이 차지 하는 크기 이다.)

이것에 대한 실마리로는 Virtual Size에서 찾을 수 있습니다. 실제 파일에서의 사이즈는 0인데 왜 저렇게 메모리에서의 사이즈는 큰 것일까?

이유는 압축해제 코드와 압축된 원본 코드는 두째 섹션에 존재 합니다.

파일이 실행되면서 먼저 압축해제 코드가 실행되고, 원본코드를 첫째 섹션에 해제 시키는 것 입니다.

그렇기에 실제 파일의 크기는 0인것이고, 메모리에서의 크기가 저런 것 입니다.



두째 섹션의 실제 크기와, 메모리 크기를 보면 알 수 있습니다.

 

 

프로그램은 http://bbolmin.tistory.com/47 에서 가져 왔으며 CodeEngn Basic 6번 문제 입니다.

 

PUSHAD 의미 - CPU 레지스터값들을 모두 스택에 넣는 명령어

POPAD 의미 - 반대로 스택에 넣은 값들을 CPU 레지스터로 복귀시키는 명령어

의문점 왜 PUSHAD POPAD를 하는것일까?


 

PUSHAD가 일어나기 전



PUSHAD가 일어난 이후 스택의 상황



EAX~EDI의 값까지가 순서대로 들어가 있음을 확인 할 수 있습니다 둘째 섹션의 주소 ESI(00424000)와 첫째 섹션의 주소 EDI(00401000)을 셋팅 합니다.

ESI가 가르키는 버퍼에서 EDI가 가르키는 버퍼로 메모리 복사가 일어남을 예상 할 수 있습니다.EDX가 가르키는 곳은 NULL으로 초기화가 되어 있습니다.EDX로부터 데이터를 읽어서 압축을 해제한 후 EDI에 저장을 시킬 것 입니다.

또한 ESI+FFFDD000의 값은 23000으로 VA와 사이즈가 같음을 확인 할 수 있습니다.



값들이 복사 됨을 확인 할 수 있습니다.

 



전체적으로 큰 루프 안에서 ESI가 가르키는 곳에 있는 값을 가져와서  EDI가 가르키는 값들을 복사함을 알 수 있습니다.



이렇게 여러 곳에서 EDX의값을 가져와서 EDI의 값으로 넣음을 확인 할 수 있습니다.

이것이 압축 해제 루프 입니다.



 



JMP 0042990E로 계속 가게 되며, 0값으로 세팅 되어있는 첫째 섹션에 값을 계속 복사 함을 알 수 있습니다. 004299C2 POP ESI에 브레이크 포인터를 걸고 F9실행을 시키면은 첫째 섹션에 모두 압축 해제된 코드가 쓰여지었던 것을 확인 할 수 있습니다.


 

IAT 셋팅 부분 입니다.



 



프로그램에서 사용 하는 API의 이름 문자열들이 저장 되어 있습니다.

004299F4 명령어의 GetProcAddress를 이용해서 API 시작 주소를 얻은 후에 EBX 레지스터가 가르키는 원본 프로그램 IAT 영역에 API 주소를 입력 합니다. 이 과정은 API 이름 문자열이 끝날 때 까지 반복 됩니다.



EBX에 저장되는 스크린샷 입니다.

 



그 뒤 스택에 EAX~ EBP까지 넣은 후 POPAD를 하는 모습입니다.

POPAD를 한 이후 CPU는 이렇게 변경이 됩니다.



 

모든 압축해제 과정이 끝나면은 OEP로 점프를 하게 됩니다.



이 부분이 OEP로 점프 하는 부분입니다.

 

 

 

 

이렇게 실습을 하면서 몇 가지 의문점을 가지게 되었습니다.

첫째. PUSHAD POPAD를 하는 이유

패킹된 파일은 루프를 돌면서 연산을 하게 됩니다. (두째 섹션의 압축해제 루틴 때문에) 이러면서 레지스터가 수정이 되는데 기존 레지스터가 수정 될 수 있기 때문에 PUSHAD로 레지스터를 밀어 넣어서 저장해두고, 루틴이 모두 끝나고 정상 코드를 실행시킬 때 이 레지스터들을 돌려 받기 위함 입니다.

 

둘째. 왜 섹션이 두 개 인가

이것은 개인적으로 생각한 것은, 어차피 PE View에 보인 PE구조들은 패킹된 프로그램의 구조 이기 때문에 정상 PE섹션이 아니고, 단순 만들어진 섹션으로 두째 섹션에서 첫째 섹션으로 원래 코드를 풀어놓는 작업은 다시 말해 처음서부터 다시 섹션을 만들어내는 과정이라고 생각 했습니다.

 

셋째. 스택에 하드웨어 브레이크 포인트를 걸어 바로 OEP를 가는 방법은 어떻게 가능한가?

이것은 첫째 의문점을 쓰다 보니까 알게 되었습니다.

저장된 레지스터로 바로 이동하기 때문에, 저장한 레지스터는 건드려지지 않은 원래 파일의 레지스터이고 이것이 브레이크포인트가 걸려있다가 돌려받은 시점에서 실행 되기 때문에 그 부분은 POPAD 부분이기 때문에 바로 OEP를찾을 수 있는 것 이었습니다.

 

요약.

1. UPX는 실행압축이다. 그래서 메모리 용량 절약과 코드들을 감춘다.

2. 맨 처음 ESI+FFFDD000의 값은 둘째 섹션 VA와 같다.

3. PUSHAD POPAD를 하는 이유는 레지스터 백업에 있다.

4. UPX는 둘째 섹션부터 시작하며, 둘째 섹션에는 해제루틴과 원래의 코드를 가지고 있다. 그리고 순서대로 실행되면서 해제루틴으로 ESI가 가르키는 버퍼에서 EDI가 가르키는 버퍼로 메모리 복사가 일어 난다. 그리고 나서 OEP로 점프 한다.

5. 루프마다 복사되는 영역과 값들이 모두 다르다.

6. 바로 POPAD BP를 걸거나 PUSHAD를 한 이후 그 레지스터에 BP를 걸은 뒤에 실행 시키면은 바로 OEP를 찾을 수 있다.

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

gdb 잘나와있음  (2) 2012.11.09
[시스템 기초] 스터디(1주차)  (0) 2012.11.08
[안티디버깅] UPX packer 이해  (0) 2012.11.08
[안티디버깅] Anti-Debuging(안티디버깅) 기초  (2) 2012.11.08
리버싱 워게임 사이트  (0) 2012.10.27
system 링크  (0) 2012.07.21

댓글(0)

[안티디버깅] Anti-Debuging(안티디버깅) 기초

CAT-Security/미분류|2012.11.08 13:10

안티 디버깅에는 2가지의 그룹이 있습니다.

static그룹 -> 맨 처음 실행될 때 안티 디버깅이 실행, 한번만 해제하면 되는것 입니다.

dymamic그룹 -> 실행 중에 계속 해제를 해주어야 함, 디버거 트레이싱을 방해하는 것 입니다.

 

디버깅 트레이싱이란? F8

 

안티 디버깅은 디버기 프로세스에서 자신이 디버기 당하는지 여부를 파악하는 기법

발견하면 종료코드를 실행하거나(대부분) 실행에 방해를 하는 코드를 실행

 

안티디버깅의 목적

디버거 탐지방법

디버거 환경탐지

디버거 강제 분리

회피 방법은 탐지 코드에서 얻어오는 정보를 변경함

 

현재 프로세스 디버깅을 판단하기 위해 PEB 구조체 정보 이용 합니다.

PEB 구조체 정보를 이용하는 것이 현재 가장 잘 사용되는 안티 디버깅 기법입니다.

PEB 구조체 주소는 FS 세그먼트 레지스터가 가르키는 TEB 구조체를 이용하여 구할 수 있습니다.

 

안티디버깅에 사용되는 중요 PEB 멤버

+0x002 BeingDebugged : Uchar

+0x00c Ldr                  : ptr32 _PEB_LDR_DATA

+0x018 ProcessHeap       : Ptr32 Void

+0x068 NtGlobalFlag       : Uint4B


 

TEB

TEB는 이미지 로더와 다양한 윈도우 DLL에 대한 컨텍스트 정보를 담고 있으며이들 요소들이 유저모드에서 구동되기 때문에 유저모드에서 쓰기가 가능한 구조체가 필요 했습니다. 그래서 이 구조체는 커널모드에서만 쓰기가 가능한 시스템 주소 공간이 아닌 프로세스 주소 공간에 위치합니다.


 

PEB

유저 주소상에 존재하는 PEB는 이미지 로더힙관리자그외 윈도우 시스템 DLL등 유저모드상에서 접근할 필요가 있는 정보를 가지고 있습니다.

 

FS 레지스터

08386부터 등장 하였으며 BASE Address 0xffdf000이며 커널 모드 에서는 KPCR(Kernel’s Processor Control Regin) 구조체를 유저모드에서는 TEB 구조체를 가르키고 있습니다.

 FS:[0] TEB의 시작 위치를 가지고 있습니다.





PEB구조체를 구하는 방법은 4가지가 있습니다.
[1] FS 레지스터를 사용하는 방법
[2] NtCurrentTeb()
를 사용하는 방법
[3] ZwQueryInformationProcess()
를 사용하는 방법
[4] GetThreadContext(), GetThreadSelectorEntry()
를 사용하는 방법


[1]
FS
라는 세그먼트 레지스터가 존재하는데, 이 레지스터가 TEB를 지정합니다
따라서 PEB를 구하기 위해 FS:[0x30]을 가져옵니다.


[2]
ntdll.dll
NtCurrentTeb() 함수를 사용하는 방법입니다. 이 함수는 내부적으로 첫번째 방법과 마찬가지로 FS 레지스터를 사용합니다.
TEB
를 구하고 TEB+0x30을 가져옵니다.

[3]
ZwQueryInformationProcess
의 두번째 인자에 ProcessBasicInformation를 넣어 호출하면 PROCESS_BASIC_INFORMATION를 얻을 수 있습니다
[4]
첫번째 방법과 마찬가지로 FS 레지스터를 읽어오는데, API를 이용합니다.

 

안티 디버깅은 OS 의존성이 있기 때문에 사전에 이를 확인하는 것이 좋습니다.

다양한 디버거 플러그인들이 있고, 계속 변형된 버전이 나오고, 플러그인에서 지원되지 않는 방법이 존재하기 때문에 동작 원리와 기본 회피 방법을 공부하는 것이 큰 도움이 됩니다.


 

IsDebuggerPresent()

IsDebuggerPresent() API PEB.BeingDebugged(PEB 구조체 +0x002)의 값을 참조하여 디버깅 여부를 판별 합니다.



IsDebugg가 실행됨을 확인 할수 있습니다.

F7을 따라서 가보도록 하겠습니다.



 

네 괜히 따라갔다가 피 봤습니다.

여기가 아니었네요. 한 시간 헤맸습니다. 왜 없지? 하면서 하하 ㅠㅠㅠ

 



isDebuggerpresent()는 함수 이기 때문에, 함수 호출을 할거 생각해서 calls 함수들의 목록을 살펴 보았습니다.

 




커널영역에서 호출됨을 확인하고, 브레이크 포인터를 걸어주고 따라가서 확인해 보겠습니다.


 


TEB 구조체를 이용해서 PEB 구조체를 찾는모습이 보입니다.

TEB 주소를 구하고 FS[0x18] -> TEB

여기서 DS[EAX+0x30] -> PEB

그리고 PEB에서 +0x2한 것이, +0x002 BeingDebugged : Uchar 이 값입니다.

이 값이 디버거로 실행될시 1로 셋팅되고, 그냥 실행될시 0으로 셋팅이 됩니다.



따라가서 패치를 해주면은

 



 

디버거없다라고 출력이되면서 우회함을 알수 있습니다.

 

 

 

+0x068 NtGlobalFlag : Uint4B

프로세스가 디버깅 중일 때는 NtGlobalFlag 0x70으로 셋팅 되어 집니다.

 



아래는 0x70과 비교해서 디버깅의 여부를 확인하는 코드이며 PEB의 주소값 +68인 것을 알고 있으니



FS:[30]의 주소로가서, 주소값 +68을 하게 되면은 0x70이 박혀있음을 확인할 수 있습니다.

이 값을 변경해준다면은 우회할 수 있게 됩니다.

 

Ldr(+0xc)

디버깅 프로세스는 힙 메모리 영역에 자신이 디버깅 당하는 프로세스라는 표시를 합니다.

힙영역에 사용하지 않은 영역을 0xFEEEFEEE값으로 채워버리는 것 입니다.

 

같은방식으로 FS:[30]으로 찾아간 뒤에 주소값에서 +c를 해 줍니다.



이 주소를 찾아 아래로 내려가면은 FEEEFEEE가 가득 차있는 것을 볼 수 있습니다.

NULL로 덮어쓰면은 회피 가능 합니다.

 



 




 

GetProcessHeap(+0x18)

PEB.ProcessHeap멤버에서 Flags멤버(+0xc) FoceFlags멤버(+0x10)은 정상 실행일 때는 2 0으로 셋팅이 됩니다. 디버거로 실행될때는특정한 값으로 셋팅 됩니다.



즉 저 값들을 2 0으로 셋팅 해주면은 우회 할 수 있습니다.

 

 

 

NtQueryinformationProcess()

 

디버거 탐지에 사용되는 것은 ProcessDebugPort(0x7) ProcessDebugObjectHandle(0x1E) ProcessDebugFlags(0x1F) 입니다.

 

이중 0x7은 프로세스가 디버깅 중일 때 할당 됩니다. ProcessInformationClass 파라미터에 0x값을 입력하면 debugPort를 얻을 수 있습니다.

ProcessDebugPort(0x7)이 디버깅중이 아니라면 0이 셋팅 되고, 디버깅중 이라면 0xffffff가 셋팅 됩니다. 그래서 이 값을 바꿔주면 우회가 가능 합니다.

 

 

 

CheckRemoteDebuggerPresent() 안티디버깅

[i] IsDebuggerPresent()Api와 비슷하게 디버깅 여부를 판별해주는 함수 입니다.

안에 NtQueryinformationProcess API를 이용 하고 있습니다.

 



 

CheckRemoteDebuggerPresent()의 정보를 받아와서 Call로 실행을 시킵니다.

저 내부함수로 들어가게 되면은 NtQueryInformationProcess를 이용함을 알 수 있습니다.

 

 







내부 함수의 모습 입니다.

우회방법은 그 밑에 점프문을 우회시켜주는 방법과 ProcessDebugFlags(0x1f)의 인자값 bDebugFlag값을 변경해주는 것 입니다.

 

 

FindWindow 함수 회피



이 함수는 잘 알려져있는 이름 혹은 환경등을 검색하여 그 조건이 맞다면은 디버깅을 중지시키는 안티디버깅 입니다.

즉 디버거가 시스템 안에서 구동되어 질 때 쉽게 찾을 수 있습니다.

chFind = FindWindow(L”ollydbg”,0);등의 소스 입니다.

chind NULL이 아니면 윈도우의 핸들을 찾은것이고, 종료 시킬것 입니다.

 

 

우회하는 방법으로는 find call 함수로 FindWindowA 를 찾고, class에서의 값을 변조시키는 방법으로 우회가 가능하다. GetWinddowText등도 비슷한 함수 입니다.

 

 

NtQuerySystemInformation()

디버깅 환경을 체크하는 안티 디버깅 기법에 대한 설명

이 기법은 현재 OS Debug Mode로 부팅되었는지 판단하는 안티 디버깅 기법이다.

ntdll!NtQuerySystemInformatin()API는 현재 동작중인 OS 시스템에 대한 다양 한 정보를 구할수 있는 함수입니다.

API가 리턴되면 시스템 디버그 모드인 경우 debugger Enabled 1이 셋팅 됩니다.

회피 방법으로는 올리디버거로 불가능하고 boot파일을 수정하거나 명령입력을 해야 합니다.

그러면 OS가 일반 모드로 부팅 됩니다.

 

 

 

 

NtQueryObject

 

디버거가 실행 중일 경우 : DebugObject 타입의 객체가 생성

 -> DebugObject 타입의 객체 생성 유무를 검사하여 디버깅 여부 검사

TypeName 필드를 유니코드  “DebugObject”와 비교 후

   TotalNumberOfObject 필드 또는 TotalNumberHandles 필드 검사

→ 0이라면 정상 상태

→ 0보다 크다면 디버깅 상태

 

우회방법 : 스택에 저장되는 “DebugObject” 대신 다른 값을 넣어줌

 

 

 

 

NtSetInformationThread
ntdll!NtSetInformationThread
ZwSetInformationThread 시스템 함수를 감싸고 있습니다.

아래는 함수 타입 설명이다.

NTSYSAPI NTSTATUS NTAPI NtSetInformationThread(
    IN HANDLE ThreadHandle,
    IN THREAD_INFORMATION_CLASS ThreadInformationClass,
    IN PVOID ThreadInformation,
    IN ULONG ThreadInformationLength
);

 

디버깅 당하는 쪽(디버기)에서 강제로 디버거를 떼어내는 기법에 대한 설명 입니다.

ZwSetInformationThread() API를 사용하면 자신을 디버깅하고 있는 디버거를 뗴어낼 수 있습니다.

첫째 인자 - 스레드에게 정보 셋팅

두째 인자 에 ThreadHide From Debugger(0x11) 값을 입력하면 디버거 프로세스가 분리 됩니다. 그래서 이 두째 인자를 0으로 셋팅 해주거나 API를 후킹 하는 방식으로 파라미터를 조작 할 수 있다.

 

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

[시스템 기초] 스터디(1주차)  (0) 2012.11.08
[안티디버깅] UPX packer 이해  (0) 2012.11.08
[안티디버깅] Anti-Debuging(안티디버깅) 기초  (2) 2012.11.08
리버싱 워게임 사이트  (0) 2012.10.27
system 링크  (0) 2012.07.21
cogegate 300문제 풀이(ida)  (0) 2012.06.09

댓글(2)