본문 바로가기

My Study/Programming&Theory

Thread Injection ( Code Injection )

이번에 알아볼 내용은 Thread Injection입니다. 다른 말로는 Code Injection이라고도 하는군요.

해당 내용은 CreateRemoteThread를 사용한 Dll Injection을 공부하신 분이라면 이해하는데 별 어려움이 없을 것입니다.
왜냐하면 형태가 비슷하기 때문이죠 ^^;

제가 Thread Injection을 공부하게 된 계기는 Dll Injection은 쫌 불편한거 같아서 입니다.
보통 Dll Injection을 하려면 exe파일에서 Dll파일을 특정 위치에 Drop을 시킵니다.
이 드랍을 시키는 일이 쫌.. 코드상 더러운거 같기두 하구요.

일단 설명을 시작하도록 하겠습니다.
( 모든 그림은 클릭 하시면 원본 사이즈로 볼 수 있습니다. )
=========================================================
Thread Injection은 말 그대로 Thread를 대상 프로세스에 넣어버리는 것입니다. 그림을 보시겠습니다.

일단 큰 과정면 그려보았습니다.
1, 2, 3 순서대로 실행이 됩니다.

먼저 실행 코드에서 대상 프로세스에 공간을 할당합니다. 그 후 Thread를 그 공간에 삽입시키고 다시 실행 코드에선 
CreateRemoteThread 함수를 사용해 해당 스레드를 실행시키는것입니다.

먼저 위 설명대로 C코드를 짜보겠습니다.

main 함수와 main함수에서 생성시키는 스레드 함수 부분입니다.

여기선 크게 볼 코드는 없습니다. 이제 Thread_Injection(PID) 부분을 보시겠습니다.

아마 Dll Injection할 때와 별로 다른점은 없어보입니다.

주석으로 모든 설명을 달아놨으니 따로 설명은 하지 않겠습니다.
이제 afterFunc 부분과 ThreadProc_Injection부분을 보시겠습니다.

위에서 afterFunc와 ThreadProc_Injection함수의 주소를 빼면서 ThreadProc_Injection함수의 크기를 구한 것입니다.
(참고 : 컴파일 시 Release로 해주셔야 ThreadProc_Injection의 크기를 제대로 구할 수 있습니다. )

그러면 이제 모든 코드가 완성 된거 같으니 한번 컴파일 해보고 실행시켜보겠습니다.

메모장을 킨 순간 오류가 발생하게 됩니다. 우리가 원하는건 cmd 창인데 오류창이 떴군요. -_-;;
한번 왜 오류가 났는지 디버그를 해보겠습니다. 


WinDbg로 바로 분석해보았습니다.

접근하면 안되는 곳에 접근해서 오류가 났고 모듈 이름은 notepad에 스레드 ID 704에서 오류가 난거 같습니다.
한번 찾아가보겠습니다.

스레드 번호 704로 가서 코드를 봐보았습니다. 일단 코드를 보니 Thread Injection은 제대로 된거 같습니다.
아래는 제 프로세스에서 Injection할 Thread 부분입니다.
Hex Dump부분을 비교해 보시면 제대로 Injection은 됬습니다.

그러면 왜 오류가 난것일까요??
그 이유는 이렇습니다.
두번째 줄을 보시면 push 0x402124를 하고 있습니다.
제 프로세스에서 가상주소 0x402124에는 "cmd.exe"라는 문자열이 있지만
notepad.exe에서 0x402124에는 "cmd.exe"라는 문자열이 없습니다. 당연한 결과입니다.

그리고 제 프로세스에서 0x402020에는 kernel32.dll:WinExec의 주소가 있지만 notepad.exe에는 없는게 당연합니다.
즉, 잘못된 주소를 push하고 있고 잘못된 주소를 call하고 있는 것입니다. 이러니 오류가 날 수 밖에 없는 것입니다.

이제 오류의 원인을 알았으니 다시 코드로 돌아와서 코드 수정을 하도록 하겠습니다.
해결방법은 제가 원하는 주소들까지 전부 notepad.exe에 넣어주는 것입니다.
일단 필요한 값들을 넘겨줄 구조체를 하나 선언했습니다.


이제 스레드를 인젝션 시켜주는 함수를 봐볼탠데, 수정시킨 함수를 보여드리겠습니다.

주석으로 설명은 다 달아놨습니다.
추가된 코드로는 inject구조체 변수에 값을 채우는 것과 그 inject구조체 변수 값을 대상 프로세스에 넣어주는 부분입니다.
그리고 CreateRemoteThread부분에서도 인자가 NULL이 아닌 inject구조체 변수가 들어간 주소를 전달해주고 있습니다.

이제 인젝션할 스레드 코드를 보시겠습니다.

WinExec를 호출하는데 바로 대상 프로세스에 넣었던 구조체에 접근해서 해당 주소에 있는 값을 호출하고 있습니다.
" cmd.exe "도 대상 프로세스에 넣었던 값으로 인자를 전달해주고 있습니다.

이제 모든 코드 구현과정이 끝난거 같습니다. 다시 컴파일 후 실행시켜 보겠습니다.

메모장을 키니 cmd창이 떴습니다 ^^ 성공인거 같군요. 

마지막으로 올디로 notepad.exe에 들어있는 구조체 값과 스레드를 봐보고 마치겠습니다.

먼저 구조체를 WriteProcessMemory 한 후 입니다.

제대로 들어왔습니다.

이제 Thread를 WriteProcessMemory한 후 를 보시겠습니다.

역시나 제대로 들어왔습니다.

[ESP+4]는 구조체의 주소를 가져오고 있습니다.
그리고 [ESP+64]는 WinExec주소를 가져오고 있습니다. 제가 buf[100]을 설정해버려서 그렇군요.

전혀 오류가 날 껀덕지가 없는 코드입니다. 당연히 실행하면 위 그림처럼 제대로 실행도 되구요 ^^

감사합니다.