Lab01-01.exe와 Lab01-01.dll 파일을 분석하여라.



1.    바이러스토탈에 파일을 업로드한 후 보고서를 보자. 기존 안티바이러스 시그니처에 일치하는 파일이 존재하는가?


-       Trojan.Agen.16384SS, Agent5.CDE, Trojan.Win32.Generic!BT 등 여러 파일 존재

 




2.    이 파일은 언제 컴파일 됐는가?


-       PE ViewIMAGE_NT_HEADERS > IMAGE_FILE_HEADER > Time Date Stamp를 확인해본 결과 2010/12/19 16: 16: 19 UTC에 컴파일 되었음을 확인 가능

 




3.    이 파일이 패킹 되거나 난독화 된 징후가 있는가? 그렇다면 무엇으로 판단했는가?


-       PEiD로 확인한 결과 패킹 되거나 난독화 된 징후는 없으며 해당 프로그램은 Microsoft Visual C ++ 6.0에서 컴파일 되었음

 




4.    임포트를 보고 악성코드 행위를 알아낼 수 있는가? 그렇다면 어떤 임포트인가?


-       LAB01-01.EXEKERNEL32.DLLMSVCRT.DLL을 임포트하고 있음. MSVCRT.DLL은 큰 의미가 없으나 KERNEL32.DLLCopyFileA, CreateFileA, CreateFileMappingA, FindFirstFileA, FindNextFileA함수를 사용 하는 것으로 보아 파일을 탐색하여 복사하는 작업을 하며 strings 함수를 통해 확인한 결과 C:\라는 문자열이 존재하는 것으로 보아 탐색 대상은 C:\으로 보임


-       LAB01-01.DLLKERNEL32.DLL, WS2_32.DLL, MSVCRT.DLL을 임포트 하고 있으나 KERNEL32.DLL, MSVCRT.DLL은 큰 의미를 갖지 않음. 다만 WS2_32.DLL은 특정 기능을 하나 Function명이 날라가 있어 Ordinal값을 통해 확인한 결과 closesocket, connect, htons, inet_addr, recv, send, shutdown, socket, WSAStartup, WSACleanup 함수를 사용 하는 것으로 보아 특정 대상과 통신하는 행위를 함을 알 수 있음




 

5.    감염된 시스템에서 검색할 수 있는 다른 파일이나 호스트 기반의 증거가 존재하는가?


-       다음은 strings LAB01-01.EXE의 실행 결과임



Kernel32.dll대신 kerne123.dll이라고 작성된 것으로 보아 정상적인 파일은 아님을 알 수 있음




 

6.    감염된 장비에서 이 악성코드를 발견하기 위해 사용한 네트워크 기반의 증거는 무엇인가?


-       Strings LAB01-01.dll의 실행결과는 다음과 같음



127.26.152.13이라는 문자열을 확인 가능한 것으로 보아 이 프로그램은 네트워크 통신을 하고 있음을 알 수 있음

 




7.    이 파일의 목적은 무엇이라고 판단했는가?


-       C:\ 밑의 파일들을 복사하여 127.26.152.13으로 전송하는 프로그램이라 판단됨

리눅스 명령어

file: 파일의 종류를 조사하는 명령어

readelf: ELF파일의 정보를 표시하는 명령어

strings: 파일 안에 들어있는 문자열을 추출하는 명령어

grep: 파일 안의 내용에서 찾고 싶은 문자열을 찾는 명령어

 

트레이서

strace: 리눅스 프로그램이 호출하는 시스템 콜을 추적한다.

ltrace: 리눅스 프로그램이 호출하는 공유 라이브러리 함수를 추적한다.

 

디버거

GDB: 리눅스의 CLI기반의 디버거

OllyDbg: 윈도우 실행파일인 PE형식의 바이너리를 분석할 수 있는 디버거

Immunity Debugger: OllyDbg와 유사한 부분이 매우 많지만 파이썬 API를 제공하며, 힙 분석에 강한 면모를 보인다.

x64dbg: 64비트 PE파일 분석도 지원하는 디버거

WinDbg: 윈도우용 디버거이다. GUI형태지만 많은 조작을 명령어로 처리한다. 커널단 디버거로 사용가능하다.

 

프로세스 메모리 에디터

CheatEngine: 윈도우에서 사용할 수 있는 프로세스 메모리 에디터 중 하나

 

역어셈블러

IDA: 고성능 역 어셈블러

objdump: 리눅스용 역 어셈블러

 

디컴파일러

Hex-Rays: IDA와 함께 사용하는 디컴파일러로 C언어형태의 의사코드로 변형해준다.

Retargetable: Retargetable 디컴파일러(http://retdec.com/)은 웹기반으로 사용할 수 있는 디컴파일러다. 실행파일을 업로드 해야한다는 단점이 있다.

ILSpy: .NET프레임워크의 CIL을 대상으로 한 오픈소스 디컴파일러다. CILC#코드로 변환할 수 있다.

dex2jar / JD: 안드로이드가 실행되는 가상머신인 달빅 VM의 바이너리 코드를 자바 바이너리 코드인 .class 파일로 변환하는 프로그램이다. 그리고 JD는 자바 바이트코드를 자바 소스코드로 변환하는 디컴파일러다.

 

Radare2

radare2는 바이너리 분석을 할 때 도움이 되는 프로그램 집합으로 다양한 도구가 포함되어 있다.

radiff2: 바이너리 차분 추출도구

rabin2: readelf-like 바이너리의 정보추출 도구

rafind2: 바이트 패턴 검색 도구

rahas2: 해시 계산도구

rarun2: 프로그램의 실행 환경을 지정해서 실행할 수 있는 도구

rasm2: 어셈블러 / 디스어셈블러

rax2: 변수 형태 변환 도구

radare2: 위의 도구를 종합한 것

라이브러리로 구현되어 있어서 도구 개발이 간단하다. GUI는 아직 지원하지 않으나 ASCII기반의 인터페이스와 웹 인터페이스가 잘 구현되어 있다. 그러나 사용법이 쉽지 않다.

 

바이너리 에디터

iBored: GUI형태의 바이너리 편집 프로그램이다. 바이너리 파일 뿐 아니라 디스크 블록 편집까지도 가능하다.

Bz: 윈도우용 바이너리 에디터로 시스템 자원을 많이 차지하지 않는다.

ghex: 리눅스에서 작동하는 GUI기반 바이너리 에디터다.

010 editor: 고성능 텍스트, 바이너리, 디스크이미지, 프로세스 에디터다. 바이너리 파일의 형식을 인식하고 분석해 헤더 필드의 값을 표시하거나 스크립트를 사용해 작업을 자동화하는 등 CTF를 진행하는데 큰 도움을 줄 수 있다.

Vim + xxd: 리눅스환경에서 바이너리를 간단하게 편집할 일이 있을때 추가 프로그램을 설치하지 않고 Vimxxd를 조합해 간단한 바이너리 편집을 할 수 있다. Vim–b옵션을 사용해 바이너리 파일을 불러오고 명령어 모드에서 :%!xxd를 입력해 xxd 명령어를 호출한다. 파일을 편집하고 :%!xxd –r을 입력해 편집한 내용을 반영하면 된다.

Easy_CrackMe

 

Reversing.kr의 첫번째 문제입니다.

파일을 다운 받아 실행하면 다음과 같은 창이 뜹니다.



 

값을 입력해서 맞지 않으면 다음과 같은 창이 뜹니다.



 

이 문제는 Password를 찾는 문제가 될듯 합니다.

 

OllydbgEasy_CrackMe를 열도록 하겠습니다.

 

Excutable modulesEasy_CrackMeEntry Point가 적혀 있네요.

Easy_CrackMeEntry Point0x00401188라고 적혀 있습니다.

 

이곳으로 이동하겠습니다.

Easy_CrackMe.text 섹션에 들어온듯 합니다.

 

우리가 하고자 하는 것은 password를 찾는 것입니다.

입력값이 password가 맞는지 검증을 통해 값이 맞다면 맞다는 출력을,

값이 틀리다면 값이 틀리다는 출력을 하겠죠.

위에서 보았듯이 값이 틀릴때는 “Incorrect Password”가 출력이 됩니다.

 

그럼 Incorrect Password 문자열 출력 전후로 해서 password를 비교하는 부분이 있을겁니다.

 

그럼 먼저 Incorrect Password를 찾아보도록 하겠습니다.

Text strings referencedIncorrect Password가 있네요.

저기로 이동해보도록 하겠습니다.

 

0x00401135부분이 Incorrect Password라는 MessageBox를 띄우는 부분으로 보입니다.

이 부분은 0x004010B5, 0x004010CD, 0x0040110B, 0x00401112에서 Jump되는데요.

즉 네부분에서 조건을 검사하고 그것이 맞지 않다면 이부분으로 넘어 오는 것으로 보입니다.

 

그럼 각 부분에 중단점을 걸고 프로그램을 실행하여 값을 입력해보겠습니다.

중단점에서 멈췄습니다.

이 윗부분에서 조건을 검사하고 조건이 맞지 않기 때문에 메시지 박스 쪽으로 넘어 가게 되겠죠.

 

이 윗부분을 확인해보도록 하겠습니다.

이 부분이 첫번째 조건 검사부분 입니다.

 

트레이스 하면서 동작을 하나씩 분석하도록 하겠습니다.

이쪽 루틴에 들어와 메모리에 공간을 100byte확보하여 줍니다.

그리고 ECX 0x18을 넣고, EAX의 값을 0으로 바꿔 줍니다.

 

그리고 0x00401094에서 스택에 0x64를 넣어주고, 0x00401096의 코드를 통해 EDI부터 EDI+24byte까지를 0으로 초기화 해줍니다.

 

그리고 0x004010AA에서 GetDlgItemText을 호출하여 입력한 값을 Buffer(0x0019F9E8)에 읽어옵니다.

https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms645489(v=vs.85).aspx

 

그리고 읽어온 값의 두번째 글자(입력값: ABCDEFGHIJKLMNOP)a인지 확인 합니다.

 

만약 입력한 값의 두번째 글자가 a가 아니라면 Incorrect Password메시지 출력부로 이동하게 됩니다.

 

입력값의 두번째 글자를 a로 바꾸고 진행하면 두번째 조건 검사부로 넘어가게 됩니다.

 

두번째 조건 검사부 입니다.

스택에 25y라는 문장이 들어있는 주소와 입력값의 세번째 글자가 들어있는 주소를 스택에 넣고 함수를 하나 호출합니다.

 

호출된 함수의 내부는 다음과 같습니다.

 

0x00401156에서 ECX2를 넣고 바로 아래에서 ECX0인지 검사해서 분기를 나눕니다. 0x00401181에서 MOV EAX, ECX하는 것으로 보아 ECX0이면 함수를 종료하는듯 합니다.

 

그리고 EBX2를 넣고, EDIESI에 입력한 문자열의 세번째 글자의 주소를 넣어줍니다.

그리고 EAX0으로 만들어 주고 REPNE SCAS BYTE PTR ES:[EDI]를 수행합니다.

REPNE : 같지 않을 때까지 반복 수행

SCAS BYTE PTR ES:[EDI] : 1ByteEDI의 값과 AX의 값을 비교

즉 같지 않을 때까지 EDI1Byte씩 늘려가며 AX와 값을 비교 진행 합니다.

 

그리고 NEG ECX를 통해 ECX의 부호를 반전시키고 EBX와 값을 더해줍니다.

그리고 EDI에 세번째 입력 글자의 메모리 주소를 넣고, ESI5y의 주소를 넣고 다시 비교합니다.

REPE CMPS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]이므로 ESIEDI의 값이 같을 때까지 반복 진행합니다.

그리고 AL5y5를 집어넣고, EDI-1과 비교합니다. 이렇게 입력값의 세번째 글자와 5와 비교하게 됩니다.

그리고 AL값이 EDI-1보다 크다면 0x0040117F, 값이 같다면 0x00401181로 이동하게 됩니다.

 

0x0040117F에서는 ECX에 보수를 취하고 0x00401181에서는 ECX의 값은 EAX에 넣어줍니다. 그리고 레지스터의 값을 복구하고 함수를 리턴해 줍니다.

 

현재 넣어준 값은 잘못된 값이므로 EAX1이 들어가고 RETN하게 됩니다.

 

그리고 EAX의 값이 0이 아니라면 다시 Incorrect Password로 넘어가게 됩니다.

 

그럼 5y와 값을 비교한다는 것을 알았으므로 다시 입력값을 수정하여 두번째 조건 검사부로 이동하겠습니다.

사용자 입력값의 세번째 글자와 5y를 비교하는 부분입니다.


0x0040116F에서 5를 비교하고 0x00401176에서 y를 비교합니다.

값이 같으므로 0x0040117B의 코드를 통해 0x00401181로 가서 EAX0을 전달하고 리턴하게 됩니다.

 

EAX의 값이 0이므로 세번째 조건 검사부로 이동하게 됩니다.

 

ESI“R3versing”의 주소값을 넣어주고, EAX에 입력값의 4번째 글자의 주소를 넣어줍니다.

그리고 거기서 한글자씩 뽑아서 비교를 하여 값이 다르다면 0x00401102로 이동합니다.

 

그리고 캐리 플래그를 포함하여 EAX에서 EAX값을 뺍니다.

그리고 EAX의 값이 0아니라면 Incorrect Password로 이동합니다.

그럼 R3versing과 비교한다는 것을 알았으므로 이를 넣어 다시 실행하도록 하겠습니다.

 

R3versing과 사용자 입력값의 세번째부터의 글자가 동일하다면 사용자 입력값의 해당 글자가 NULL인지 확인합니다.

즉 문자열의 끝인지 확인하는 것이죠, 문자열의 끝에 도달했다면 0x004010FE로 이동합니다.


그렇게 두번 검사를 진행하고 다시 0x004010DA로 이동하여 반복합니다.

 

만약 글자가 더 많다면 위의 그림처럼 되어 EAX1이 남고 다시 Incorrect Password 출력부로 이동하게 됩니다.

 

입력값을 다시 맞게 수정하여 실행하도록 하겠습니다.

정상적으로 코드를 빠져나와 XOR EAX,EAX연산을 통해 EAX0으로 만들어 줄것으로 보입니다. 그리고 JMP를 통해 SBB EAX,EAXSBB EAX,-1을 건너 뜁니다.

 

그리고 사용자 입력값의 첫번째 글자의 값이 0x45(E)인지 검사합니다.

현재 첫번째 글자의 값이 A이므로 Incorrect Password부분으로 이동하겠네요.


그럼 다시 입력값을 수정하여 실행하도록 하겠습니다.

성공적으로 문제를 해결하였습니다.

올바른 패스워드는 Ea5yReversing이었습니다.

너무 세세하게 적었나 내용이 길어졌네요

+ Recent posts