티스토리 뷰

Self Creation 이란 ? 

- 실행 중에 자기 자신을 자식(Child) 프로세스로 생성시키는 애플리케이션들을 말합니다.

같은 실행 파일이면서 부모(Parent)로 실행될 때와 자식으로 실행될 때 서로 다르게 동작합니다. 다시 말해서 프로세스가 자기 아래 그림과 같이 자신을 자식 프로세스로 실행시키는 것을 말합니다. 악성코드에 자주 나오는 유형이니 숙지하면 좋은 기법입니다.


* 실습 파일(DebugMe2.exe)는 리버싱 핵심원리의 실습 파일을 사용했습니다.



부모 프로세스는 콘솔(Console) 창에 parent 문자열을 출력하고 자식 프로세느는 child 문자열을 출력합니다. 이와 같이 하나의 실행 팡리에서 두 가지 형태의 동작을 수행하는 것을 확인할 수 있습니다.



[동작 원리]


[Self-Creation 동작 원리]


Create Child Process(SUSPEND mode)

- 부모 프로세스가 실행되면 main() 함수가 호출되고 main()에서 SUSPEND 모드로 자식 프로세스를 생성합니다. 자식 프로세스가 SUSPEND 모드로 생성되면, Import DLL들은 로딩되지만 메인 스레드가 멈춘 상태가 됩니다.


메인 스레드는 프로세스가 생성될 때 기본적으로 생성되는 스레드로, EP 코드를 실행시키는 가장 중요한 역할을 수행합니다. 따라서 SUSPEND 모드로 실행된 프로세스는 메인 스레드가 멈추면서 EP 코드가 실행되지 못하고 아무런 동작을 하지 못하는 상태가 됩니다.



Change EIP

- 부모 프로세스에서 자식 프로세스의 코드 실행 주소를 임의로 변경이 가능합니다. 현재 멈춰있는 자식 프로세스의 메인 스레드의 컨텍스트(Context)를 얻어서 EIP 멤버를 원하는 주소 값으로 변경한 후 적용하면 됩니다.



Resume Main Thread 

- 자식 프로세스의 멈춰져 있는 메인 스레드를 실행합니다.(앞에서 변경한 코드 주소를 실행)



* API 함수 흐름 = CreateProcess() -> GetThreadContext() -> SetThreadContext() -> ResumeThread()



[디버깅 실습]


Self-Creation 기법을 디버깅할 때 고려해야 할 사항은 바로 디버깅 중에 새로 생성되는 자식 프로세스를 어떻게 시작 시점부터 디버깅할 수 있느냐 하는 것입니다. 우선 부모 프로세스를 디버깅하여 자식 프로세스의 EP가 어느 주소로 변경되는지를 확인해야 합니다.


JIT(Just-In-Time) 디버깅 방법으로 진행합니다.


* JIT 디버깅 

- 실행 중인 프로세스에 예외가 발생했을 때 OS에서 자동으로 지정된 디버거를 실행하여 해당 프로세스에 Attach해주는 것을 말합니다. 예외가 발생한 위치에서부터 디버깅을 진행할 수 있기 떄문에 예외 원인 파악에 도움이 됩니다.


JIT 디버깅을 하기 위해서 설정을 해주어야 합니다. 일단, 올리디버거의 Options에서 Just-in-time debugging을 클릭합니다.



JIT 디버깅창이 뜨면 아래와 같이 Make 로 JIT 디버거를 설정합니다.




아래는 레지스트리로 설정 유무를 알 수가 있습니다. 




이 실습 예제 파일의 디버깅 목표는 자식 프로세스의 (새로운) EP 코드부터 정확히 디버깅을 하는 것입니다.

Self-Creation 기법은 자기 자신을 자식 프로세스로 실행하면서 시작 코드(EP code) 위치를 변경하기 때문에 먼저 부모 프로세스를 디버깅하여 자식 프로세스의 시작 코드 주소를 얻어와야 합니다. 그리고 JIT 디버깅 방법으로 자식 프로세스를 디버깅하면 됩니다.




[부모 프로세스 디버깅]


부모프로세스의 main() 함수로 들어옵니다.



CreateProcess로 자식 프로세스를 생성하는 부분으로 가서 실행을 하면 SUSPEND 모드의 자식 프로세스가 생성이 됩니다.



내려오다 보면 아래와 같이 GetThreadContext()/SetThreadContext() 를 볼 수가 있습니다.




아래에 SetThreadContext() 함수의 첫 번째 인자에 MOV로 401000을 넣어줍니다. 즉, 자식 프로세스의 메인 스레드 컨텍스트 구조체를 GetThreadContext()로 구하여 CONTEXT.Eip 값을 SetThreadContext() 함수를 통해 자식프로세스 주소로 변경하는 코드입니다. 




바로 위의 그림에서 401186 줄을 보면 401000이 자식프로세스의 주소이고 [LOCAL.264]가 CONTEXT.Eip 입니다. 

CONTEXT 구조체의 시작 주소는 GetThreadContext()/SetThreadContext() 함수의 두 번째 파라미터를 확인하면 되는데 위에서주소를 보면 0012FAA0 입니다.




위에서 구한 자식 프로세스의 메인 스레드를 시작시킵니다.




자식 프로세스가 종료할 때까지 기다리는 상태가 됩니다.




[자식 프로세스 디버깅]

SetThreadContext() 함수에서 00401186 줄을 보면 00401000(자식프로세스)으로 변환시킵니다. 그러므로 401000의 VA를 파일 옵셋으로 변환하면 400이 나옵니다. WinHex로 400 오프셋으로 가서 6A를 CC로 변경합니다. 즉 파일 옵셋 0x400의 0xCC 코드가 실행되면, EXCEPTION_BREAK_POINT 예외가 발생하게 됩니다.


 ->>>>> 


* 0xCC

- INT3 명령어(Break Point)를 의미하는 1바이트 크기의 IA32 Instruction입니다.




바꾼 뒤에 다른이름으로 저장을하고 실행을 하면 오류가 뜹니다. 여기서 프로그램 디버그 버튼을 누르면 위에서 설정한 JIT 디버거로 설정된 OllyDbg가 자동으로 실행되어 오류 프로세스에 Attach 됩니다. 이때 OllyDbg는 예외가 발생한 코드를 보여줍니다. 이제 다시 0xCC코드를 이전 코드 0xx6A로 변경하고 자식 프로세스 디버깅을 실행하면 됩니다.



참고 : 리버싱 핵심원리



'리버싱 > 정리' 카테고리의 다른 글

RVA to RAW 계산  (0) 2015.12.29
[PE Image Switching 디버깅]  (0) 2015.08.14
[서비스 디버깅 방법]  (0) 2015.08.12
서비스 프로세스 동작 원리  (0) 2015.08.12
IDA pro 사용법  (0) 2015.08.12
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함