1) DllMain의 주소는 무엇인가?
IDA pro에서 실습 파일을 열면 자동으로 dll main함수부터 보여줍니다. 때문에 main의 주소는 1000D02E임을 바로 알 수 있습니다.
2) Imports 윈도우를 이용해 gethostbyname을 탐색해보자. 임포트 위치는 어디인가?
우선 gethostbyname이라는 함수에 대해 알아보겠습니다.
우리가 접속하고자하는 사이트에 대한 정보들을 알아오기위한 함수입니다. 그 정보들에는 ip등이 있곘습니다.
import window를 보고 검색을 통해 api를 찾습니다.
gethostbyname함수의 import위치는 .idata 섹션의 100163CC라는 위치에서 사용할 수 있도록 명시되어있습니다.
3) gethostbyname에 함수는 몇 개인가?
gethostbyname을 호출한 함수들을 살펴보기 위해서는 XREF라는 기능을 사용합니다.
gethostbyname에 커서를 놓고 X를 누르면 호출한 함수들의 목록을 볼 수 있습니다. type에 p는 함수를 호출하는 부분, r은 읽어오는 부분임을 의미합니다. 우리는 호출하는 부분, p타입에서만 살펴보겠습니다.
함수들의 개수가 여러가지가 아니라, 몇개의 함수에서 여러번 호출하고 있음을 알 수 있습니다.
10001074에서 3번, 10001365에서 3번, 10001656에서 1번, 1000208F에서 1번, 10002CCE에서 1번 호출하였습니다. 그래서 5개의 함수에서 호출하였고 총 9번 호출하였음을 보았습니다.
4) 0x10001757에 위치한 gethostbyname 호출을 보면 어떤 DNS 요청이 이뤄지는지 알 수 있는가?
문제에서 gethostbyname이 호출된 주소지를 알려주었습니다. G키를 통해 이동할 주소를 입력하고 이동합니다.
gethostbyname에 들어가는 사이트 주소값을 알아보아야합니다.
그 사이트 주소값은 바로 위에보이는 push로 들어가는 eax레지스터에 우리가 원하는 dns쿼리를 위한 사이트 주소값이 들어가있을 것 같습니다. 더 위에 보면 offset_1001904에 있는 값을 eax에 넣고, 그 eax값에 add 0Dh합니다. 따라서 eax에 들어가는 값은 10019040이 아니라 1001904D가 될것입니다. 그래서 1001904D부터 읽는 값이 gethostbyname의 인자값으로 들어가 있겠습니다.
ida에서 임의로 값에 대한 정보를 aThisIsRdoPics라고 정해놓았습니다. 더블클릭해서 따라가보겠습니다.
아까 push명령어에서 add 0Dh를 하였습니다. 13바이트 떨어진 위치부터가 gethostbyname의 인자값으로 들어갑니다. 그래서 13바이트 떨어진 위치에 있는 값은 pics.practicalmalwareanalysis.com입니다. 이게 인자값이 되겠습니다.
5) 0x10001656에 있는 서브루틴에서 IDA Pro는 지역변수 몇 개를 인지하고 있는가?
해당 주소로 이동하기위해 G를 사용합니다.
지역변수가 몇개가 있는지 확인해보겠습니다. var_675, var674, ... 그 다음은 var_670,,이라고 써있어야할텐데 hModule, timeout등으로 되어있습니다. 이는 sub_10001656이라는 함수 내부에서 호출되는 windows api함수에서 사용하는 지역변수이기 때문입니다. 그래서 지역변수 이름인 var_670으로 사용되기보다 api함수에서 사용되는 파라미터의 이름인 hModule으로 ida pro가 자동으로 변경해준 것입니다. 자동으로 변경해주는 이유는 분석가가 분석을 할 때 파라미터 이름으로 되어있는 것이 분석하기 편하기 때문입니다.
그래서 지역변수가 24개인 것으로 세었지만, 맨 아래의 IpThreadParameter는 제일 상단에 인자값이라고 되어있습니다. 이것은 지역변수가 아니라 10001656이 인풋으로 받는 데이터 값이기 때문에 빼고 카운팅합니다. 그래서 지역변수는 총 23개입니다.
6) 0x10001656에 있는 서브루틴에서 IDA Pro는 파라미터 몇 개를 인지하고 있는가?
파라미터 값은 IpThreadParameter이므로 1개입니다.
7) Strings 윈도우를 이용해 디스어셈블리 내의 문자열 \cmd.exe /c를 찾아보자. 어디에 있는가?
[shift+f12]를 통해 strings를 볼 수 있습니다. [alt+T]로 cmd.exe를 검색하고 더블클릭합니다.
cmd.exe가 있는 영역이 xdoors_d로 되어있는데 일반적인 섹션명이 아닌것으로 보아 악성코드 제작자가 만들어놓은 것으로 추측할 수 있습니다.
8) \cmd.exe /c를 참조하는 코드 영역에서 무슨 일이 발생하는가?
XREF기능을 사용하여 [X] 눌러서 cmd.exe 를 사용하는 함수 위치를 보겠습니다. 더블클릭하여 들어갑니다.
cmd.exe /c 를 사용하는 코드 영역은 100101D0입니다. 이 영역에서는 GetSystemDirectoryA를 이용해서 windows\system32\밑에 cmd.exe 를 실행하려고 하는 것으로 보입니다.
또한 CreatePipe*라는 함수와 함께 cmd.exe /c를 실행시키는 부분이 있다고 하면 reverse shell 이구나 라고 추측하게 됩니다.
*감염pc의 cmd.exe, 소켓을 이어주는 함수, 이후 감염pc와 해커의 소켓통신이 가능해질 수있음
9) 같은 영역 0x100101C8에서 dword_1008E5C4는 경로를 지정하는 전역변수로 보인다. 악성코드는 어떻게 dword_1008E5C4를 설정하는가? (힌트 : dword_1008E5C의 상호 참조를 이용하라)
G키를 통해 원하는 위치로 이동합니다. dword_1008E5C4의 값과 ebx를 비교하고있습니다.
dword_1008E5C4를 더블클릭하거나 미리보기를 통해 볼 수 있습니다. 특별한 값은 없는 것으로 확인되어 XREF기능을 통해 사용되고있는 위치를 보았습니다.
아래두개는 cmp, 비교하는 것이고 우리가 볼 부분은 mov, 변화가 생기는 함수를 보겠습니다. 더블클릭!
mov dword_1000E5C4, eax
eax에는 기본적으로 어떤 함수가 실행된 이후에 발생된 리턴값을 저장합니다. 그 위의 sub_10003695 함수를 실행시킨 후에 발생하는 리턴값이 들어가있겠습니다. 이 리턴값이 무엇인지 보기위해서는 sub_10003695값을 더블클릭합니다.
GetVersionA라는 함수를 호출한 뒤 운영체제 버전에 대한 정보를 리턴값으로 주는 함수였습니다. 그리고 dwPlatformId값을 체크해서 그 아이디값이 2인지 여부를 확인합니다. 2라는 값은 윈도우nt일때 입니다. 윈도우즈nt가 맞다면 리턴값이 0이 되어서 반대로 제로플래그는 1이 설정되게 되어있습니다. setz는 제로플래그가 1일 경우 al을 1로 설정하는 명령어입니다. 아니라면 0으로 설정이 됩니다.
이것을 c코드로 보면 더 이해하기가 쉽습니다. [f5]
10) 0x1000FF58에서 서브루틴으로 수백 라인은 문자열을 비교하기 위한 일련의 memcmp비교다. Robotwork와 문자열 비교가 성공적으로 이뤄지면 무슨 일이 일어나는가? (memcmp가 0을 반환)
memcmp에는 인자값이 두가지가 들어갑니다. 첫번째 인자값과 두번째 인자값은 모두 문자열이 들어갑니다.
두개가 같은지 비교한 후 같다면 0, 아니면 0이 아닌값을 반환하게 됩니다.
우선 G키를 이용하여 1000FF58로 이동합니다.
이동 후에 Robotwork을 찾아야하는데 [shift+f12]를 통해 strings윈도우에 들어가고, [alt+T]로 strings를 검색합니다.
섹션이름이 xdoors_d이고 앞에서 아마 악성코드 제작자가 만들어놓은 곳이라고 추측하였습니다. robotwork, .. 등의 문자열과 관련된 변수들이 있는걸로 보아 .data영역일 가능성이 높습니다.
offset부분인 aRobotwork부분에 커서를 놓고 XREF기능을 사용해보겠습니다.
문제에서 보았던 memcmp부분을 볼 수 있습니다. 또 문제에서 주소값이 1000FF58이라고했는데 검색했을때 바로 나오지 않았던 이유는, 해당 주소부분에서 너무 멀리 떨어져있었기 때문입니다.
0 이 아닌 값, 즉 같지 않을 때는 10010468로 점프하게 되고, 같다면 call sub_100052A2라는 함수를 호출합니다. 따라서 robotwork라는 문자열이 들어와서 비교를 하고 맞다면 100052A2로 가니 이쪽을 살펴보면 될 것 같습니다. >더블클릭
특정 레지스트리키를 오픈하고 있는 것이 보입니다.
오픈이 성공하면 RegQueryValue함수를 사용하여 WorkTime이라는 키 값을 검색합니다. WorkTime이라는 키 값은 30초라는 값이 저장이 되어있으면 worktime에 저장된 데이터와 30을 가져다가 atoi함수를 사용하여 문자열을 정수형으로 바꿔줍니다. 30초를 바꾸고 sprintf를 사용해서 [Robot_WorkTime: ] %d라는 문자열을 넣어주는데 이 %d에 atoi로 변환한 30초를 넣어주는 것입니다.
call 100038EE에 커서를 대면 함수의 상세 내용을 볼 수가 있는데, socket s 라는 것으로 보아 네트워크상에서 무언가를 보내거나 수신하는 것으로 추측이 됩니다.
따라서 이 함수는 worktime이라는 쿼리, 레지스트리에 저장된 값을 읽어와서 문자열로 합쳐주고, 그 결과값을 네트워크를 통해 해커에게 전송하는 행위를 하는 함수라고 생각이 듭니다.
11) PSLIST 익스포트는 무슨 역할은 하는가?
export window로 보겠습니다.
들어가면 1008E5BC에 1을 넣고 sub_100036C3 함수를 호출합니다.
getversion함수를 통해 운영체제 버전을 확인하고 있습니다. 각각의 운영체제에 대한 버전을 명시하고있는 표가 있는데, msdn에서 확인 가능합니다.
아래 lpVersionInformation이라는 파라미터에 기재되어있는 osversioninfo를 클릭하면 됩니다.
https://docs.microsoft.com/ko-kr/windows/win32/api/winnt/ns-winnt-osversioninfoa
그럼 우리는 이 함수를 보기좋게 바꾸도록 하겠습니다. 함수에 커서를 두고 n키를 누르거나, 우클릭> rename~ 으로 변경합니다.
함수 이름이 변경된 것을 확인하였고, 아래 sub_10006518에 대한 함수도 알아보겠습니다.
sub_10006518의 기능은 process list를 출력하는 것이라고 추측이 가능합니다. 이것도 rename합니다.
처음에는 os버전을 체크하고 process list를 출력하고 있는 함수입니다.
그 아래 함수들도 체크해보니 동일하게 pslist를 출력하는 함수여서 이름을 변경해줍니다.
그런데 전체적으로 다시 보니 process list를 출력하는 함수가 두번이나 호출이되지만, 함수는 다릅니다.
이유는 pslist의 str이라고 해서 문자열 값을 자세히보니 처음에 나왔던 함수에서는 push eax 한번, 뒤에서는 두개의 인자값을 받아 push 를 두번 합니다.
->pslist export함수는 처음에는 운영체제 버전을 확인하고 그 이후에는 process list를 출력하는 역할을 합니다.
12) 그래프 모드를 이용해 sub_10004E79 상호 참조 그래프를 그려보자. 이 함수에 진입하기 위해 호출하는 API 함수는 무엇인가? 해당 API 함수에만 기반을 두고 이 함수를 어떤 이름으로 변경하겠는가?
getsystemdefaultLangID함수의 기능은 현재 운영체제에서 사용하는 언어에 대해 확인하기위한 것입니다.
이 함수 이름을 바꾸기 위해서는 sub_10004E79에 커서를 두고 N키를 누릅니다.
메뉴바에 우클릭> 그래프 선택 후 위에서 아래로 내려가는 네번째 아이콘을 클릭합니다.
send는 소켓을 통해 무언가를 전송할때 사용되는 함수입니다. 아마 GetSystemDefaultLangID로 운영체제가 사용하는 언어에 대한 정보를 검색한 뒤에 그 정보를 해커에게보낸다고 추측이 가능합니다.
13) DllMain이 직접 호출하는 윈도우 API 함수는 몇 개인가? 두번째 깊이(depth of 2)에서 몇 개인가?
dllmain함수로 검색을 통해 이동하고, 그래프 아이콘 제일 마지막을 클릭하여 값을 1로 수정해줍니다.
7개의 함수들이 호출되고있습니다.
depth를 2로 하면 더 자세하게 보이게 됩니다.
14) 0x10001358에서 Sleep 호출이 존재한다. (sleep까지 수밀리초 값을 파라미터로 갖는 API함수) 코드 후반부를 보면 이 코드가 수행되려면 프로그램이 얼마동안 sleep하는가?
아스키 문자값을 integer정수값으로 변경하는 atoi함수도 보입니다.
off_10019020의 값은 ThisIsCti30이라는 주소값을 가지고 있습니다. 이 주소값 + D의 위치는 30이 시작되는 위치입니다. 그래서 eax에는 30이 들어가게되겠습니다. 이 값은 문자열로 들어가게 되어 atoi로 변환하는 것입니다.
>imul eax, 3E8h는 10진수로 변환하면 1000입니다. 그래서 곱하는 것이니까 30000이 되겠습니다.
3만 밀리세컨드-> 30초
보기쉽게 코멘트를 달아놓았습니다. 정답은 30초동안 sleep한다. 입니다.
15) 0x10001701에서 소켓을 호출한다. 세 가지 파라미터는 무엇인간?
https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket
ipv4, 소켓 스트링 타입, tcp 프로토콜을 사용함을 알 수 있습니다.
16) 소켓과 IDA Pro에서 명명한 심볼 상수 기능을 이용해 이 파라미터를 좀 더 유용하게 할 수 있겠는가? 변경 후 파라미터는 무엇인가?
설정을 더 보기 편하게 바꾸어주었습니다.
17) 명령어 옵코드 0xED의 사용법을 찾아보자. 이 명령어는 Vmware 탐지를 수행하는 VMXh 매직 문자열로 사용한다. 이 악성코드는 이를 이용하고 있는가? Vmware를 탐지하는 다른 증거가 있는가?
[alt+B] , 바이트 찾는 문자열에서 VMXh에 해당하는 opcode 값=564d5868
동일한 곳에서 두번 사용되고있습니다. 더블클릭하여 해당 부분으로 이동하고 option설정을 합니다.
문제에 나오는 ED는 in 명령어에 있습니다.
R을 이용해서 문자열값으로 변경하여 보겠습니다. VX라는것은 우리가 앞에있는 호스트 운영체제에서 vm의 게스트 운영체제 안으로 파일을 옮기거나 뺄때 둘이 서로 통신하는 포트의 이름입니다.
이 함수의 이름도 수정해주고 호출된 부분중 맨 첫번째부분으로 이동합니다.
vmware체크를 한 뒤에 가상머신을 찾았는지 해커에게 알려주는 것 같습니다.
18) 0x1001D988로 점프해보자. 무엇을 찾을 수 있는가?
단축키G를 통해 이동합니다. .data섹션에 있습니다. 그리고 암호화 된듯한 것으로 추정되는 문자열들이 있습니다.
19) IDA 파이썬 플러그인을 설치했다면(IDA Pro 상용 버전에는 포함되어 있음) Lab05-01.py를 실행해보자. IDA 파이썬 스크립트는 이 책의 악성코드와 함께 제공한다. (커서가 0x1001D988에 위치해야 함) 스크립트 실행 후 무슨 일이 일어났는가?
메뉴에 file> script file> Lab05-01.py
적용 후에는 암호화되어있던 내용이 제대로 보이게 바뀌었습니다.
20) 동일한 위치에 커서를 두고 이 데이터를 ASCII 문자열로 어떻게 변환할 수 있는가?
a를 누르면 실제로 우리가 보고싶은 문자열이 일렬로 보이게 됩니다.
21) 문자 편집기로 스크립트를 열어보자. 어떻게 동작하는가?
0-80까지 루프를 돌면서 바이트를 호출해서 각 값을 얻습니다. 그리고 연산을 실행하고 바이트로 패치하는 코드가 되겠습니다.
'study > 악성코드분석&리버싱' 카테고리의 다른 글
Windbg commands, 윈디버거 명령어들 (0) | 2020.10.15 |
---|---|
IDA Pro 프로그램 (0) | 2020.06.10 |
x86 디스어셈블리 (0) | 2020.05.31 |
기초 동적 분석, Lab03-04.exe (0) | 2020.05.24 |
기초 동적 분석, Lab03-03.exe (0) | 2020.05.24 |