1. Quick & Dirty Tips
for x64 malwares
somma (fixbrain@gmail.com)
2. x64 - segmentation
flat segment model
DS, ES, SS 는 무시 됨
GDT[DS], GDT[ES], GDT[SS] 도 당근 무시
3. x64 – virtual memory
flat segment model 이니까…
얘도 참고
4. RIP + 변위(displacement) 형태로 주소를 지정하는 방식
x86 에서는 control transfer instruction 에서만 사용 가능했음
데이터의 접근을 좀더 편하게 해줌
global data 접근 시 base address 에 의한 기준 재배치가 필요 없어짐
addressing range
signed 32bit range (rip 로부터 +2Gb, -2Gb)
x64 – RIP relative addressing
7. • 레지스터 사이즈 확장 및 추가
• GDTR, LDTR, IDTR, TR 레지스터가 8 바이트 주소를 가리키도록 확장
• EFLAGS -> RFLAGS 로 확장
• CR0 ~ CR4 가 8 바이트로 확장
• CR8 레지스터 추가
• DR9 ~ DR7 가 8 바이트로 확장
• R8 ~ R15 범용 레지스터 추가
• segmentation
• ES, DS, SS 는 사용되지 않음 (디스크립터의 base, limit, attribute 는 무시 됨)
• FS, GS 의 경우 MSR 에 주소를 매핑
• MSR [IA32_FS_BASE]
• MSR [IA32_GS_BASE]
• MSR [IA32_KERNEL_GS_BASE]
x64 system level architecture
8. x64 ABI (Application Binary Interface, a.k.a. calling convention)
http://msdn.microsoft.com/en-US/library/9z1stfyw(v=vs.80).aspx
9. x64 ABI (Application Binary Interface, a.k.a. calling convention)
• 파라미터 전달은
• rcx, rdx, r8, r9 또는 xmm0, xmm1, xmm2, xmm3, 나머지는 stack 을 이용해서.
• 파라미터 사이즈가 8 바이트보다 크면 포인터 연산을 통해 rcx, rdx, r8, r9, 또는 stack 을 통해 전달
• 리턴 값은?
• 8 바이트로 커버된다면 eax
• double, _m128 등은 xmm0
• 구조체의 경우
• caller 가 변수를 할당하고, 주소를 rcx 파라미터로 전달, rdx 파라미터에 첫 번째 파라미터 전달
• DEMO) func_a(), func_b()
10. x64 ABI (Application Binary Interface, a.k.a. calling convention)
• rcx, rdx, r8, r9 에 파라미터가 전달되지만
• caller 는 *항상* 레지스터에 전달되는 파라미터를 위한 스택을 할당한다.
• + prolog, epilog…
• + exception handling…
11. Global API Hooking
• [ DLL | CODE ] injection
• 실행 중인 모든 프로세스들에 dll injection
• App Init registry key
• PE file patch (IAT patch)
• Windows Message Hook
• CreateRemoteThread( LoadLibrary )
• …
• 새롭게 생성되는 프로세스들에 dll injection
• CreateProcess
• CreateProcessInternalW
• …
• MmCreateSection( )
• …
• ZwResumeThread( )
• …
• Code Patch
• IAT hook
• EAT hook
• Inline hook ( == detour )
• code caving
• …
12. • CreateRemoteThread( LoadLibrary_ptr )
• vista 부터 service 는 session 0, user process 는 1,2,3,4… 에 생성 됨
• CreateRemoteThread 는 다른 세션의 프로세스에 스레드를 생성 할 수 없음
Session
Window st
ation (Win
Sta0)
Desktop (d
efault desk
top)
User applic
ation or se
rvice
DLL injection – CreateRemoteThread 로는 안됩니다.
14. DLL injection – hook 을 위한 새로운 구조 필요
• injection 을 컨트롤 하는 서비스 (session 0) 생성
• 타겟 세션에 프로세스 생성 후 dll injection 수행
• 새로운 세션이 생겼을 때의 처리 필요(e.g. new terminal service session)
• hook or callback
15. DLL injection – WoW
x64 Native
x64 Native
x86 WoW
x86 WoW
x64 Native
x86 WoW
16. DLL injection – WoW
• x64 프로세스는 WoW 프로세스에 thread 를 생성할 수 없고,
• WoW 프로세스는 x64 프로세스에 thread 를 생성할 수 없다.
• 따라서 remote thread 생성에 기초한 dll injection 을 하려면
• injection 을 수행할 프로세스를 생성하고
• 생성된 프로세스가 dll injection 을 수행해야 한다.
17. DLL injection – UAC (권한문제)
• PROCESS_ALL_ACCESS 권한으로 타겟 프로세스를 오픈하려면
• SeDebugPrivilege 권한을 enable 시켜야 함
• 프로세스에 SeDebugPrivilege 가 없는 경우 활성화 불가 -> dll injection 불가능
UAC off UAC on
18. DLL injection – UAC (권한문제)
• 새로 생성되는 프로세스는 대부분 explorer.exe 의 자식프로세스
• UAC on 인 경우 explorer.exe 는 SeDebugPrivilege 없음
• child process 에 dll injection 을 할 수 없는 상황이 발생함
• 그래서 안정적인 Global Api hook 을 구현하려면 별도의 서비스를 생성하는 것이 답!
• UAC 는 항상 켜고 쓰는 것이 좋다는…
20. Detour 101
• JUMP 명령어
• 조건 분기
• near jump (동일 세그먼트내에서 분기)
• fat jump (다른 세그먼트로 분기)
• cpu 가 segment 갱신을 자동으로 해줌
• direct jump vs indirect jump (reg/mem)
• x64 에서는 `jmp far direct` 는 허용되지 않음 (0xEA opcode 없음)
21. Detour in x64
• jmp rel8off (EB cb)
• jmp -5
• hot patching
• jmp rel32off (E9 cd)
• Near jump with the target specified by a 32-bit signed displacement
• 5byte, +2Gb, -2Gb ( 64 비트 메모리 공간을 모두 사용할 수 없음 )
• jmp rel64off 명령은 없다! (있으면 편할텐데…)
• 64 bit indirect jump
mov rax, xxxxxxxx
jmp rax
• 64 비트 메모리 공간을 다 사용할 수 있음
• 12바이트
• 레지스터 값을 망가뜨림 (volatile이라고 해도…) – 뭔 문제가 생길지 누가 알아 !
• push & mov [rsp+4] xxx trick
push {4byte lower address} ; 4bytes pushed, 8bytes allocated on stack
mov dword ptr [rsp+4], {4byte higher address} ; adjust 4byte higher address
ret ; pop eip;
; jmp eip
• 14 bytes
• 레지스터 값을 망가뜨리지 않음