2018. 1. 22. 03:31ㆍ0x03 Reversing Theory/역공학 연습문제
특정 악성코드의 일부 코드라고 한다. 이 코드에서 배울 수 있는 건 아주 많다.
그래서 하나하나 다 적으면서 복습을 해보려고 한다.
넘나 재밌는거.....!!
하루 하루 지날 때 마다 한 단계씩 지식이 늘어나는 것 같아서 너무 좋다 !
그럼 잡담은 그만하고 공부하자.
핵심 :
1. 작성 된 DLL 일부 이다
2. 목표로 삼은 컴퓨터의 IDT 변조를 파악한다. -- IDT의 존재에 대해 오늘 처음 알았죠.
3. 목표로 삼은 컴퓨터가 윈도우즈에 로그인 되어 있는지 파악한다. (explorer.exe를 통해) -- 이렇게 파악을 한다는 거면 컨셉이 RCE인가.?
4. 목표로 삼은 컴퓨터에 영향을 줄 스레드를 만든다. -- 스레드 안에서 조용히 은닉되어서 악의적 행위를 하려고 하는 것 같다. 내가 최근에 작성해 본 코드도 스레드안에서 자동으로 체력을 깎이게 만들어 봤으니 이 체력이 악의적 행위로 탈바꿈 되면 악성코드가 되는 것이다 ㅠㅠ
BOOL __stdcall DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
_DllMain@12 proc near
push ebp -----> 기저 프레임포인터를 저장
mov ebp, esp --> 함수 프롤로그 설정
sub esp, 130h --> 현 함수의 스택 크기 설정
push edi --> edi를 스택에 저장
sidt fwrod ptr [ebp-8] --> 6바이트 IDT 레지스터를 특별한 메모리 영역에 씀
mov eax, [ebp-6] # 이런주소의 값을 대입하는 건 처음 보았다. // IDT 기저주소를 읽음
cmp eax, 8003F400h
jbe short loc_10001C88
cmp eax, 80047400h
jnb short loc_10001C88
// ------------> 기저주소의 변형여부를 탐지 함
if (IDT > 0x8003F400 && IDT < 0x8003F400)
{
return FALSE;
}
//
xor eax, eax --> 사용한 eax를 초기화 시킴
pop edi --> 스택에서 사용한 edi를 복구 시킴
mov esp, ebp
pop ebp --> 이전 함수로 돌아가기 위해 ebp를 레지스터로 복구 시킴 --> 함수 에필로그
retn 0Ch
loc_10001C88:
xor eax, eax
mov ecx, 49h
lea edi, [ebp-12Ch]
mov dword ptr [ebp-130h], 0
push eax // CreateToolhelp32Snapshot의 th32ProcessID
push 2 // CreateToolhelp32Snapshot의 dwFlags
rep stosd // ecx 반복의 경우 edi가 가리키는 곳으로 eax의 내용을 저장하고 매번 4 바이트 씩 edi를 증가 또는 감소시킵니다 (방향 플래그에 따라 다름). 일반적으로 이것은 memset-type 작업에 사용됩니다. (출처 : https://stackoverflow.com/questions/3818856/what-does-the-rep-stos-x86-assembly-instruction-sequence-do)
--... 뭔소린지...--
call CreateToolhelp32Snapshot // eax와 2를 인자 값으로 사용하는 함수
mov edi, eax
cmp edi, 0FFFFFFFFh // if(edi == -1)
jnz short loc_10001CB9
xor eax,eax --> init
//
if(edi == -1)
{
__asm
{
xor eax, eax
}
return eax
}
//
pop edi
mov esp, ebp
pop ebp // edi와 ebp를 정리하지 않으면 올바르게 retn이 되지 않는다 ( p.18 3번에서 테스트 함 )
retn 0Ch
loc_10001CB9:
lea eax, [ebp-130h] // mov dword ptr [ebp-130h], 0 로 인해 [ebp-130h] 안의 값은 0이고, [ebp-130h]의 주소를 eax에 복사
push esi // 3개의 레지스터를 스택에 push 한다
push eax --> Process32First 함수 -> lppe
push edi --> Process32First 함수 -> hSnapshot
mov dword ptr [ebp-130h], 128h // 0x128로 init
call Process32First // 시스템 스냅 샷에서 발생한 첫 번째 프로세스에 대한 정보를 검색
이 부분은 조금 많이 중요해 보여서 상세 분석을 들어 갔다. 악성코드에서 아주 유용하게 사용되는 api함수 같기도 하고..
Process32First 함수 같은 경우는 2개의 인자를 가지고 있다. 첫 번째로 HANDLE hSnapshot, 두 번째로 LPPROCESSENTRY32 lppe를 소유하고 있는 함수이다. WIN32API에서 핸들이란 아주 중요하다고 봐야 한다. 어떠한 모듈들을 다룰 때 사용되기 때문이다. 상기에서 push edi를 hSnapshot이라고 표기한 이유는 다음과 같다. edi를 어디서 썼는지 한번 살펴 보고 오자.
call CreateToolhelp32Snapshot // eax와 2를 인자 값으로 사용하는 함수
mov edi, eax
CreateToolhelp32Snapshot의 반환 값이 eax 일테고, 그 값을 edi에 대입했으니까 edi 또한 반환 된 값이라고 볼 수 있다.
그렇다면, push edi는 CreateToolhelp32Snapshot 함수에서 핸들을 반환 해온 값이라고 보면 된다.
그럼, lppe는 무슨 값을 나타낼까?
lea eax, [ebp-130h] 여기에서 보면 알 수 있듯이 지역변수 (ebp-130h)의 주소를 가리키고 있다.
lppe의 데이터 형이 LPPROCESSENTRY32 인 것으로 보아 lppe는 LPPROCESSENTRY32의 구조체 변수라고 볼 수 있다.
loc_10001C88:
xor eax, eax
mov ecx, 49h
lea edi, [ebp-12Ch]
mov dword ptr [ebp-130h], 0
push eax // CreateToolhelp32Snapshot의 th32ProcessID
push 2 // CreateToolhelp32Snapshot의 dwFlags
rep stosd
해당 루틴이 구조체를 0으로 초기화 하는 구문이라고 하는데 유독 이 부분은 이해가 안 된다...
구조체 공부를 더 깊게 해야하는 것인가 !
해결 : rep가 ecx가 0이 될 때까지 반복하는 명령어 , stosd는 edi가 가리키는 주소에 eax 저장 그렇다면 구조체 변수는 감소연산자를 가진 반복문 구문안에서 0으로 초기화가 된다고 보면 됨.
지역변수 범위 ebp-130h ~ ebp-12Ch
잠온다. 일어나서 마저 하자 ㅎㅎ
test eax, eax //eax init to 0
jz short loc_10001D24
mov esi, ds:_stricmp
lea ecx, [ebp-10Ch] // ecx에 지역변수(ebp-10Ch)주소를 설정하는데 PROCESSENTRY32에 있는 영역이 된다.
push 10007C50h // szExeFile의 주소가 0x10007C50 이다 -> 책에 따르면 'explorer.exe'라고 한다
push ecx // PROCESSENTRY32에서 szExeFile 필드
call esi ; _stricmp
add esp, 8 // stricmp가 cdecl 호출 규약이기 때문에 add esp, 0x8을 통해 스택을 지운다. 즉 esp를 올린다고 보면 된다
test eax, eax
jz short loc_10001D16
loc_10001CF0:
lea edx, [ebp-130h]
push edx // [ebp-130h] 주소를 edx에 복사 --> _Out_ LPPROCESSENTRY32 lppe
push edi --> _In_ HANDLE hSnapshot
call Process32Next // edx와 edi를 인자 값으로 사용함
test eax, eax // Process32Next의 반환 값을 and연산 취했을 때 결과에 따라 분기가 달라짐
jz short loc_10001D24
lea eax, [ebp-10Ch]
push 10007C50h
push eax
call esi ; _stricmp
add esp, 8 // esp 정리 (2번)
test eax, eax
jnz short loc_10001CF0
loc_10001D16:
mov eax, [ebp-118h] // PROCESSENTRY32's th32ParentProcessID
mov ecx, [ebp-128h] // PROCESSENTRY32's th32ProcessID
jmp short loc_10001D2A
loc_10001D24:
mov eax, [ebp+0Ch]
mov ecx, [ebp+0Ch] // eax와 ecx 둘 다 저장 해두는 군..
loc_10001D2A:
cmp eax, ecx // DllMain(ebp+8)의 매개변수 fdwReason을 읽고 0인지 검사
pop esi
jnz short loc_10001D38
xor eax, eax
pop edi
mov esp, ebp
pop ebp
retn 0Ch
loc_10001D38:
mov eax, [ebp+0Ch]
dec eax
jnz short loc_10001D53
push 0
push 0
push 0
push 100032D0h
push 0
push 0
call ds:CreateThread // 6개의 인자를 넣음
loc_10001D53:
mov eax, 1
pop edi
mov esp, ebp
pop ebp
retn 0Ch
__DllMain@12 endp
끄읏 ~
'0x03 Reversing Theory > 역공학 연습문제' 카테고리의 다른 글
p. 38 (0) | 2018.01.22 |
---|---|
p. 18 (0) | 2018.01.21 |
주저리주저리 (0) | 2018.01.21 |