#1 : http://redscreen.tistory.com/66

#2 : http://redscreen.tistory.com/67

#3 : http://redscreen.tistory.com/68

#4 : http://redscreen.tistory.com/71

 

------------------------------------------------------------------------------------------------------------------------------------------

10. 0x1000FF58에서 서브루틴으로 수백 라인은 문자열을 비교하기 위한 일련의 memcmp 비교다.

      robotwork와 문자열 비교가 성공적으로 이뤄지면 무슨 일이 일어나는가? (memcmp가 0을 반환)

------------------------------------------------------------------------------------------------------------------------------------------

일단 문제에서 주어진 문자열 "robotwork"를 찾습니다.

Strings window에서 검색기능을 이용하여 robotwork를 찾습니다.

 

해당 문자열은 xdoor_s 섹션에 있고,

상호참조 리스트를 이용하여 어디서 사용되고 있는지 확인합니다. (정말 좋은 기능이네요..)

 

다른 memcmp 함수와 동일하게 사이즈, 사용자입력값, 비교문자열 3가지 인자를

push하고 memcmp를 호출합니다.

memcmp는 두 비교문자열이 같으면 0을 결과값으로 반환합니다.

test eax eax 명령어를 수행해여 

1) 결과값 0 반환 -->  (문자열이 같음)  -->  ZF=1 세팅  -->  loc_10010468 Jump

2) 결과값 0 아님 -->  (문자열이 다름)  -->  ZF=0 세팅  -->  loc_100052A2 Jump  (다음 문자열 비교)

 

문자열이 "robotwork"와 동일하면 loc_10010468으로 점프하게 되므로 

계속 트레이싱 하며 따라가면 아래와 같은 어셈블리 코드가 나옵니다.

코드가 갑자기 길어져서 한번에 파악하기는 힘들지만,

아래부분에 분홍색 RegOpenKeyExA API와 push되는 레지스트리 관련 문자열이 가장 눈에 확 들어옵니다.

 

RegOpenKeyExA API는 성공하면 ERROR_SUCCESS(0) 을 반환하고, 핸들키값을 넘겨줍니다.

1) API 호출에 성공  -->  test eax eax 명령어를 통해 0이 반환되며, loc_10005309로 Jump (오른쪽)

2) API 호출에 실패  -->  RegCloseKey API와 함께 종료 (왼쪽)

2번 케이스의 경우, Graph overview에서 독보적인 빨간색 화살표와 함께 서브루틴이 끝나는 것을 볼 수 있습니다.

 

1번 케이스의 경우, 아래와 같은 loc_10005309 서브루틴을 실행합니다.

역시 루키라 한번에 파악은 절대 안됩니다 OTZ...

분홍색의 RegQueryValueExA, sprintf, atoi 등의 API들이 가장 잘 보이고,

파란색의 API 인자값들이 눈에 띕니다. 

가장먼저 실행되는 RegQueryValueExA는 먼저 나온 RegOpenKeyExA, RegCloseKey와 세트로 등장하는 API입니다.

Syntax는 아래와 같으며, 해당 함수를 실행하기 위해 lpValueName "WorkTime"을 포함한 6개의 인자를 push하고

ebx에 저장해두었던 RegQueryValuesExA 함수를 call 하는 부분을 위의 어셈블리 코드에서 볼 수 있습니다. 

 

만약 여기서 함수 호출에 실패하면 loc_10005379로 Jump하게 되는데,

lpValueName값을 "WorkTimes" 로 변경해서 호출합니다.

어쨋든, WorkTime 또는 WorkTimes의 값을 얻게 되면

atoi값을 이용하여 int형태로 변경한 뒤 sprintf 함수를 이용하여 지정된 형식대로 문자열을 만듭니다  --> [Robot_WorkTime : %d]

이후 sub_100038EE로 분기하여 sned 함수로 값을 전송합니다.

답 : HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion에 있는 WorkTime or WorkTimes 레지스트리 값을 전송

 

Tip. 인자(argument) vs 매개변수(parameter)

알고도 매일 까먹고 구분없이 포스팅하고 있었습니다..

인자값은 함수 호출 시 넣어주는 값을 말합니다  -->  Func("argument");

매개변수는 전달된 인자를 받아들이는 값입니다 --> void Func(char* parameter)

 

------------------------------------------------------------------------------------------------------------------------------------------

11. PSLIST 익스포트는 무슨 역할은 하는가?

------------------------------------------------------------------------------------------------------------------------------------------

PSLIST는 export window에서 찾을 수 있습니다.

 

해당 익스포트로 가보면 아래와같은 어셈블리 코드가 나옵니다.

 

초반에 또다른 서브루틴 sub_100036C3을 호출합니다.

호출 결과에 따라 test eax, eax로 인해 loc_1000705B로 Jump합니다.

즉, 값이 0이라면 앞뒤 볼것도 없이 종료라는 뜻인데, 왜그런지는 살펴봐야 합니다.

 

Tip. 서브루틴 미리보기

이러한 sub문이 나올때마다 넘어가서 이해하고 다시 돌아왔었는데

함수에 마우스를 대고 드래그로 아래를 내리니 sub문이 미리보기 형식으로 나오는 편리한 기능이 있더군요 (+삽질지수 감소)

 

내용을 보니 GetVersionExA API를 이용하여 얻어낸 구조체 VersionInformation으로 두가지 비교를 수행합니다.

1) dwPlatformId 비교

내용은 문제 9번에서 비교한 내용과 같으며, 윈도우즈 계열 플랫폼인지 확인합니다.

2) dwMajorVersion 비교

dwMajorVersion과 5를 CMP 명령어로 비교합니다.

여기서 dwMajorVersion의 의미를 알고자 MSDN에서 제공하는 표를 가져왔습니다.

운영체제 버전마다 값이 정해져 있고, 가장 낮은 버전이 5입니다. (Windowx Server 2003을 포함한 4개의 운영체제)

CMP명령어에 의해 왼쪽값(dwMajorVersion)이 5보다 낮으면 (표에 있는 운영체제보다 더 낮은 버전의 OS일 경우)

loc10036FA로 Jump하게 될것이고 더 이상의 연산을 수행하지 않고 leave명령어를 수행합니다.

Jump 하지 않는다면, 1을 리턴하고 종료합니다.

 

-----------------------------------------------------------------------------------------------------------------------------

Tip. SUB vs LOC

분석중에 갑자기 의문점을 느껴 검색해보았습니다. SUB와 LOC로 시작하는 함수들의 차이가 무엇인가...

1) 공통점 : 프로그램의 흐름이 바뀐다는 것

2) 차이점 : SUB 호출은 retn값이 있지만 LOC의 경우 retn이 없으므로 ByeBye

참고로 short은 짧은 곳으로의 Jump 라고 합니다.

이런거 하나하나 알아가게 되면서 리버싱 속도가 1~2초라도 빨라지는거 같아 재미있네요 ㅎㅎ;

-----------------------------------------------------------------------------------------------------------------------------

 

 ------------------------------------------------------------------------------------------------------------------------------------------

12. 그래프 모드를 이용해 sub_10004E79 상호 참조 그래프를 그려보자.

      이 함수에 진입하기 위해 호출하는 API함수는 무엇인가?

      해당 API 함수에만 기반을 두고 이 함수를 어떤 이름으로 변경하겠는가?

------------------------------------------------------------------------------------------------------------------------------------------

G 기능을 이용하여 sub_10004E79 주소로 넘어갑니다.

문제에 나온대로 상호 참조 그래프를 그리기 위해 [View > Grapgs > Xrefs From] 을 클릭합니다.

그러면 아래와 같은 그래프가 나옵니다.

 

위 상호참조 그래프 기능으로 인해 sub_10004E79 함수가

GetSystemDefaultLangIDSend를 호출함을 쉽게 알 수 있습니다.

해당 함수가 네트워크 소켓을 통해 언어 식별자를 전송할 가능성이 있음을 알려주므로,

함수명을 오른쪽 클릭해 send_languageID와 같은 의미 있는 이름을 붙여줍니다.

(책에 나와서 하는거지만...이런게 고수들의 좋은 습관이자 노하우 아닐까요?)

 

또한 해당 함수를 호출하는 과정을 알아보기 위해

sub_10004E79를 클릭하고 Ctrl+X 를 눌러 호출하는 곳으로 가보았습니다.

"language" 명령어를 이용하여 호출함을 확인합니다.

 

다음 포스팅에서 계속됩니다!

posted by Red_Message

#1 : http://redscreen.tistory.com/66

#2 : http://redscreen.tistory.com/67

#3 : http://redscreen.tistory.com/68

#4 : http://redscreen.tistory.com/71

 

------------------------------------------------------------------------------------------------------------------------------------------

7. Strings 윈도우를 이용해 디스어셈블리 내의 문자열 \cmd.exe /c를찾아보자. 어디에 있는가?

------------------------------------------------------------------------------------------------------------------------------------------

View > Open Subviews > Strings 를 선택하여 해당 문자열을 찾습니다. (Shitft + F12)

맨 아래부분에서 발견 가능하고, 더블클릭하면 섹션과 주소값을 알아낼 수 있습니다.

답 : xddors_d 섹션 / 0x10095B34

 

 

------------------------------------------------------------------------------------------------------------------------------------------

8. \cmd.exe /c를 참조하는 코드 영역에서 무슨 일이 발생하는가?

------------------------------------------------------------------------------------------------------------------------------------------

해당 메소드가 어떤 기능을 하는지 알아내기 위해 해당 문자열을 더블클릭합니다.

이후에 문자열의 주소를 클릭하고 상호참조 리스트를 호출합니다. (Ctrl+X)

결과는 아래와 같이 단 한곳에서 호출함을 알 수 있습니다.

gethostbyname처럼 여러군데에서 호출되지 않으니

한군데만 확인하면 어떤 기능을 하는지 확인할 수 있다는 단서를 제공합니다.

 

또한 해당 코드영역을 더 살펴보면

"Hi, Master..."

"Welcome Back...."

"Encrypt Magic Number For This Remote Shell Session..."

등등의 백도어에서 원격 접속 시 사용될 것 같은 문자열이 있습니다. 

 

CMD창을 이용하여 명령어를 입력할 가능성이 있음을 기억해둡니다.

그리고 아까 상호참조를 타고 그래프 뷰로 넘어가서 화살표를 따라 쭉쭉 내려가면

"quit", "exit", "cd" 와 같은 문자열과 함께 memcmp 함수를 발견할 수 있습니다. 

 

책에서 memcmp를 볼 수 있을거라고 매우 쉽게 설명되 있지만, 

저는 아직 숙련되지 않기도 했고, 그래프가 크게 느껴져서  삽질을 좀 많이

빨간색(FALSE), 초록색(TRUE), 파란색(무조건) 화살표의 의미를 생각하며 그래프를 타고 내려가면

그래프 오버뷰의 중간 부분에서 memcmp가 반복 됩니다.

CMD에서 명령어를 입력할때마다 memcmp함수로 어떤 명령인지 비교하는 코드겠구나..라는 생각이 들었습니다.

답 : 원격 세션 생성

 

 

------------------------------------------------------------------------------------------------------------------------------------------

9. 같은영역 0x100101C8에서 dword_1008E5C4는 경로를 지정하는 전역 변수로 보인다.

    악성코드는 어떻게 dword_1008E5C4를 설정하는가? (힌트 : 상호참조 이용)

------------------------------------------------------------------------------------------------------------------------------------------

주어진 x100101C8 주소로 넘어가면 dword_1008E5C4값이 나옵니다.

 

해당 전역변수를 더블클릭하면 .data 섹션으로 넘어가게 되는데,

그곳에서 상호참조 리스트를 확인하면 아래와 같이 3가지가 나옵니다.

 

전 포스팅에서 살펴보았듯이 R Type은 읽기만 할뿐이고,

수정하는 부분은 맨위의 W Type 하나뿐이므로, 해당 부분을 살펴보면 어떻게 무슨값을 설정하는지 알 수 있겠군요.

OK를 누르고 해당 주소지로 이동하면, 아래와 같이 sub_10003695의 리턴값인 EAX를 이용하여

전역변수에 값을 할당하는 것을 볼 수 있습니다.

 

그렇다면 sub_10003695는 무엇을 하는 서브루틴일까요?

더블클릭하여 이동하면 아래와 같이 GetVersionExA 함수를 사용하는 소스임을 알 수있습니다.

아래 소스코드가 한눈에 파악이 안되어, Syntax부터 살펴보기로 했습니다.

 

GetVersionExA API의 SynTax는 아래와 같고, lpVersionInfo 파라미터를 넣어줘야 합니다.

push eax 를 이용하여 파라미터를 넣어주었고, GetVersionExA API로 버전값을 알아낸 것으로 보입니다.

 

이후에 VersionInformation 내부의 dwPlatformId 값이 2인지 CMP 명령어를 이용하여 비교를 하게 되는데,

참고로 dwPlatformId는 아래와 같이 윈도우 버전에 관련된 변수입니다.

 

두값이 같을 경우, CMP명령어의 결과는 0이되고 제로플래그(ZF)가 1로 세팅됩니다.

ZF가 1이라면 SETZ 명령어에 의해 AL(EAX의 하위 8비트)가 1로 세팅됩니다.

 

정리하면, Windows 계열인 경우 서브루틴 sub_10003695가 1을 리턴할 것이고,

리턴되는 값이 dword_1008E5C4 값에 저장될 것입니다.

답 : 운영체제 버전 저장

 

--------------------------------------------------------------------------------------------------------------------------------------------------

Tip. CMP 그리고 JUMP (JA vs JB vs JE vs JZ)

1) CMP

CMP는 묵시적으로 Op1(Destincationm, 피연산자)에서 Op2(Source, 소스피연산자)와의 뺄셈을 수행 ex) CMP Op1, Op2

그리고 어떤 피연산자도 수정되지 않지만, 뺄셈을 수행하다보니 플래그를 수정합니다.

- Op1 - Op2 < 0, ZF=0 CF=1

- Op1 - Op2 > 0, ZF=0 CF=0

- Op1 - Op2 = 0, ZF=1 CF=0

2) JUMP

JMP와 관련된 명령어는 매우 많지만 이번 문제에서 자주 쓰이는 Jump 명령어를 정리합니다.

- JA : Jump if Above / CMP로 두 값을 비교하여 Op1(왼쪽) 크면 Jump  /  ZF = 0  and  CF = 0

- JB : Jump if Below / CMP로 두 값을 비교하여 Op2(오른쪽) 크면 Jump  /  CF = 1

- JE : Jump if Equal / CMP로 두 값을 비교하여 Op1, Op2 값이 같으면 Jump  /  ZF = 1

- JZ : Jump if Zero / 결과값이 0이면 Jump / ZF = 1

- JNZ : Jump if not Zero / 결과값이 0이 아니면 Jump / ZF = 0

 

Tip. CMP 이전에 수행하는 XOR EAX, EAX 명령어

XOR 명령어는 Overflow와 Carry 플래그를 항상 0으로 해제합니다.

또한 EAX는 서로다른 값일때만 1로 세팅되므로,

XOR EAX, EAX를 수행할 경우, 서로가 같은 값을 가지므로 0으로 초기화됩니다.

한마디로 CMP이전에 수행되는 해당 명령어는 청소도구라고 생각하면 되겠네요!

 

Tip. 함수에서 돌아온 이후 수행하는 TEST EAX, EAX 명령어

예를들어, memcmp 함수가 수행된 이후에 TEST EAX, EAX를 수행한다면 어떤 의미일까요?

TEST 명령어는 묵시적으로 두 피연산자의 대응되는 각 비트 쌍에 대해 AND 연산자를 수행하고,

결과에 따라서 플래그를 설정합니다. 또한 TEST 명령어는 연산자에 어떤 영향을 주지 않습니다.

하지만 이러한 글을 다 기억하는 것보다는, 자주 쓰이는 사례의 의미를 기억하는게 더 효율적이겠지요.

- CMP명령어는 두 OP가 동일한지를 판단하며

- TEST명령어는 두 OP가 모두 0인지 판단합니다.

즉 위에서 예로든 memcmp 함수가 시행된 이후에 EAX값에 리턴값이 설정되어 있을것이고

TEST명령으로 해당 값이 0인지 확인하는데 사용됩니다.

즉, memcmp로 비교한 문자열이 동일한가? 라는것을 TEST 명령어로 체크하는겁니다.

--------------------------------------------------------------------------------------------------------------------------------------------------

posted by Red_Message

안녕하세요. Message입니다.

<실전 악성코드와 멀웨어 분석> 책의 실습 문제 5-1을 분석합니다.

분석환경은 Windows 7 Ultimate 64x / Vmwre 12.1.0 build 입니다.

 

#1 : http://redscreen.tistory.com/66

#2 : http://redscreen.tistory.com/67

#3 : http://redscreen.tistory.com/68

#4 : http://redscreen.tistory.com/71

 

 

------------------------------------------------------------------------------------------------------------------------------------------

0. 준비

------------------------------------------------------------------------------------------------------------------------------------------

OllyDbg쓰다가 IDA쓰다가 이클립스로 개발하다가...보면 가장 혼동되는게 단축키입니다.

원래는 그때마다 검색해서 다시 감잡은 다음에 작업에 들어갔는데,

이참에 IDA에서 자주 쓰는 단축키만 정리하겠습니다.

 

일반

---------------------------------------------------------

- TextView와 Graph 화면전환 : SPACE 

- Strings Window : Shitft+F12

- 함수이동 : Ctrl+p 

- 이름검색 : Ctrl+L

- XREF 검색 : Ctrl+X 

- 주소이동 : g 

- 전단계 이동 : ESC

- 코드수정 : Alt+F2

- Text 검색 : Alt+t

- Quick View : Ctrl+1 

---------------------------------------------------------

 

디버그

--------------------------------

- BreakPoint : F2

Debugging Start : F9

- Debugging Exit : Ctrl+F2

- Step Into : F7

- Step Over : F8

--------------------------------

 

그래프모드 화살표 색상

---------------------------

------▶  False

------  True

------  무조건 Jump

---------------------------

 

------------------------------------------------------------------------------------------------------------------------------------------

1. DllMain의 주소는 무엇인가?

------------------------------------------------------------------------------------------------------------------------------------------

Function Name Window에서 DllMain을 찾습니다.

처음에는 DllEntryPoint로 착각했지만, DllMain이 따로 있었습니다.

둘의 차이점을 검색해보았으나, 명확하게 딱 이거다 라고 되어 있는걸 못찾았습니다.

스페이스키를 누르고 그래프를 살펴보았더니 DllEntryPoint가 먼저 호출되고 난 이후에

자신이 받은 인자값을 그대로 넣어주면서 DllMain을 호출하더군요.

답 : text 섹션 / 0x1000D02E

 

Tip. main에 관하여

RedAlert 에서 배포된 PE구조 문서를 보니

일반적으로 EntryPoint는 main, wmain, WinMain, wWinMain 으로 착각하기 쉽지만 (처음보는 함수도 많네요)

진정한 main은 CRT main이라고 합니다. CRT main은 C/C++ run-time startup 코드라고 불리는 함수가 따로 존재하는데,

이는 Linker에 의해 실행파일이 생성될 때 합쳐치며, main 함수도 CRT main에 의해서 호출되는 함수입니다.

CTR main은 Command-Line argument와 환경변수를 채우고,

heap 초기화, 전역변수 객체 생성자 호출, 전역변수 초기화 등을 수행합니다.

종류는 mainCRTStartup, wmainCRTStartup, WinMainCRTStartup wWinMainCRTStartup 등등..

이부분은 따로 숙지할 필요가 있겠네요.

 

 

------------------------------------------------------------------------------------------------------------------------------------------

2. Imports 윈도우를 이용해 gethostbyname을 탐색해보자. 임포트 위치는 어디인가?

------------------------------------------------------------------------------------------------------------------------------------------

Import Window에서 getbyhostname을 찾습니다.

윈도우에 포커스를 두고, gethostbyname을 타자치면 검색 기능이 활성화되어 쉽게 찾을 수 있습니다.

gethostbyname을 더블클릭하면 디스어셈블리창으로 이동되며, 주소값을 알아낼 수 있습니다.

답 : idata 섹션 / 0x100163CC

 

------------------------------------------------------------------------------------------------------------------------------------------

3. gethostbyname 함수는 몇번 호출되는기?

------------------------------------------------------------------------------------------------------------------------------------------

디스어셈블리창에서 Ctrl+X 를 입력하면 xref로 표기되는 상호참조 리스트 윈도우가 호출됩니다.

type은 호출(p)읽기(r)로 표시됩니다.

sub_10001074, sub_10001365, sub_10001656, sub_1000208F, sub_10002CCE 등 5개의

서로다른 함수에서 9번 호출됨을 알 수 있습니다.

답 : 5개의 함수에서 9번 호출

 

 

------------------------------------------------------------------------------------------------------------------------------------------

4. 0x10001757에 위치한 gethostbyname 호출을 보면 어떤 DNS 요청이 이뤄지는지 알 수 있는가?

------------------------------------------------------------------------------------------------------------------------------------------

.gethostbyname 함수는 도메인이름ex) www.daum.net 하나를 파라미터로 받는 함수입니다

상호참조 리스트에서 P type의 메소드를 클릭하여 확인하면

EAX 레지스터를 이용하여 도메인 네임 인자를 받는 어셈블리코드를 볼 수 있습니다.

 

off_10019040 주소를 더블클릭하거나 G 기능을 이용하여 주소로 점프하면

아래와 같이 "[This is RDO]pics.practicalmalware...(생략)" 소스를 발견할 수 있습니다.

 

EAX 레지스터에 0Dh 주소값을 더하는 이유는

문자열의 [This is RDO] 값을 제외하고 "pics..." 부분을 포인터로 얻기 위함입니다. 

답 : pics.practicalmalwareanalysis.com

 

 

------------------------------------------------------------------------------------------------------------------------------------------

5. 0x10001656 서브루틴에서 IDA Pro는 지역변수 몇개를 인지하고 있는가?

6. 0x10001656 서브루틴에서 IDA Pro는 파라미터 몇개를 인지하고 있는가?

------------------------------------------------------------------------------------------------------------------------------------------

스페이스바를 이용하여 그래프모드로 전환후 0x10001656으로 가거나

G단축키를 이용하여 0x10001656으로 이동하면

아래와 같은 그림에서 지역변수와 파라미터의 개수를 확인할 수 있습니다.

답 : 지역변수 23개, 파라미터 1개 (arg_0= dword ptr 4)

 

 

 

posted by Red_Message