yon11b

[SK 쉴더스 루키즈] 고급 정적 분석 - IDA로 Practical Malware Analysis Labs 05-01.dll 분석하기 본문

보안/SK 쉴더스 루키즈

[SK 쉴더스 루키즈] 고급 정적 분석 - IDA로 Practical Malware Analysis Labs 05-01.dll 분석하기

yon11b 2026. 6. 2. 02:16
반응형

IDA 기본 단축키

G           주소 이동
X           참조 찾기
N           이름 변경
;           주석
Space       그래프/텍스트 전환
Tab         의사코드 전환
Shift+F12   문자열
Shift+F5    함수 목록
Esc         뒤로가기
Enter       따라가기

 

8. \cmd.exe /c를 참조하는 코드 영역에서 어떤 동작이 수행되는가?

strings에서 \\cmd 검색을 해주자

더블 클릭해서 따라간 다음 ctrl+x로 저 문자열을 부르는 곳을 찾으러 간다.

하나밖에 안 나온다. 저거 클릭하자.

 

cmd.exe랑 command.ex로 분기를 한다. 어떤 조건일 때 분기가 되는지 궁금하다.

myVersionInfo 함수를 두 번 클릭해서 들어간 뒤, 똑같이 ctrl+X를 해주자.

우리는 저 값이 뭔지 궁금한 것이므로, write를 한 제일 첫번째 라인으로 가준다.

 

myVersoinInfo에는 sub_10003695의 결과(eax)가 들어간다.

sub_10003695로 가보자.

cmp version, 2로 비교를 하고 있다.

 

GetVersionExA

현재 운영체제 정보를 얻어오는 Windows API

https://learn.microsoft.com/ko-kr/windows/win32/api/winnt/ns-winnt-osversioninfow

내 환경은 XP이므로 cmp 결과가 0이 되고,  setz al-> al= 1이 될 것이다. 

(setz: 직전에 수행한 연산 결과로 ZF(Zero Flag)가 1이면 1을 저장, 아니면 0을 저장한다.)

AL = (VersionInformation.dwPlatformId == 2);

 

myVersionInfo 

myVersionInfo = (VersionInformation.dwPlatformId == 2);

 

dwPlatformId가 2인 경우

myVersionInfo = 1;

 

xp면 cmp myVersionInfo, ebx가 1이 되어서 왼쪽 분기문으로 간다. 그래서 cmd.exe /c를 가져오게 된다.

 

10. 0x1000FF58에서 서브루틴(함수)으로 수백 라인은 문자열을 비교하기 위한 일련의 memcmp 비교 루틴이다. robotwork와 문자열 비교가 성공적으로 이뤄지면 무슨 일이 일어나는가?

0x1000FF58은 맨 위다. 밑으로 스크롤을 내려가면서 보면 memcmp가 보인다.

robotwork가 있는 곳까지 내려 찾아주자.

 

 

두 갈래로 분기하는 것을 볼 수 있다.

 

결과가 0이면 왼쪽으로 감.

 

왼쪽으로 가면 네모 친 블록이 보인다.

 

sub_100052A2 함수를 호출하는 것을 알 수 있다.

 

 

sub_100052A2 함수는 뭐하는 녀석일까

sub_100052A2 를 두 번 클릭해서 이동해준 뒤, 그래프를 그려보자.

 

크게 두 가지 기능을 수행하는 것을 알 수 있다.

1. send

2. Reg(레지스터) 관련

 

일단 sub_100052A2 함수의 이름을 보기 쉽게 바꿔주자. robotwork 문자열 관련이므로, myRobotwork로 지어주겠다.

우클릭 후 Rename 선택하면 바꿀 수 있음

1. send

뭘 send하는지 보자. sub_100038EE 함수를 보자. 이 함수의 시작 주소는 100038EE이다.

주소 검색은 G

malloc, send, free가 있음을 확인할 수 있다.

socket으로 전달한다.

 

2. Register 관련

아까 그래프에서 보면 RegOpenKeyExA, RegCloseKey, RegQueryValueExA가 있었다.

 

RegOpenKeyExA: 레지스트리 키를 연다. (권한 획득)

RegQueryValueExA: 열린 레지스트리 키 안의 값을 읽는다.

RegCloseKey: 열어둔 레지스트리 키를 닫는다. (핸들 반환)

 

큰 흐름: RegOpenKeyExA -> RegQueryValueExA -> atoi -> RegCloseKey

 

 

RegOpenKeyExA

: HKLM\Software\Microsoft\Windows\CurrentVersion 열기

 

hkey가 80000002h == HKEY_LOCAL_MACHINE

 

C코드로 바꾸면 다음과 같다.

HKEY hKey;

if (RegOpenKeyExA(
        HKEY_LOCAL_MACHINE,
        "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
        0,
        KEY_ALL_ACCESS,
        &hKey) == ERROR_SUCCESS)
{
    // 레지스트리 열기 성공
}

 

 

RegQueryValueExA

: 레지스트리 열기에 성공하면 이어서 RegQueryValueExA 호출해서 열린 레지스트리 키(HKLM\Software\Microsoft\Windows\CurrentVersion) 안의 값(WorkTime) 읽기

: 읽은 값을 atoi()로 숫자로 변환

c로 나타내기

LONG result;

result = RegQueryValueExA(
    hKey,        // [ebp+hKey]
    "WorkTime", // aWorktime
    NULL,        // lpReserved
    &Type,       // [ebp+Type]
    Data,        // [ebp+Data]
    &cbData      // [ebp+cbData]
);

if (result != ERROR_SUCCESS) {
    goto loc_10005379;
}

 

 

그 후 로직들...

1. ebp+var_60c에 worktime 정보를 저장한다.

sprintf(
    var_60C,
    "\r\n\r\n[Robot_WorkTime :] %d\r\n\r\n",
    worktime
);

 

 

2. ebp+var_60c(worktime)를 sub_1000038EE의 인자로 전달한다.

sub_100038EE(
    s,
    var_60C,
    strlen(var_60C)
);

 

 

정리

registry 다루는 로직에서는 HKLM\Software\Microsoft\Windows\CurrentVersion  레지스트리를 열고 그 안에 있는 worktime을 꺼내서 sub_100038EE로 전달한다.

sub_100038EE에서는 data(worktime)를 send한다.

 

추론

1. worktime은 악성코드가 레지스트리에 저장해둔 동작 시간 또는 실행 시간 관련 값으로 보인다. 

그래서 이 정보를 C2로 추정되는 서버에 전송하는 흐름이라고 예측할 수 있다.

2. 사실  HKLM\Software\Microsoft\Windows\CurrentVersion 안에는 worktime 같은 값이 없다. 따라서 worktime값은 이전에 악성코드가 심어놓은 값 등으로 추론해볼 수 있다.

 

 

Q14. 0x10001358에 Sleep 호출이 있다. 해당 코드가 실행되기까지 프로그램은 얼마 동안 대기하는가?

 

10019020에서 읽은 주소에 0D를 더하고, 숫자로 변환하고, 거기에 0x3e8을 곱한 값 만큼 sleep 을 한다.

10019020 주소로 가면 100192ac를 찾을 수 있다.

 

100192ac에 가면 [This is CTI]30 문자열을 볼 수 있다.

 

[에서 시작해서 0xD를 더하면 딱 30 이 나온다.

 

30을 숫자로 변환하고(atoi), 0x3e8을 곱하면 30000이 된다.

→ 30000ms

→ 30s

728x90