본문 바로가기

Reversing

Power Merger(파일 합체기) 분석 및 분해기 제작(With Visual Basic 6.0)

네이버에 흔하게 떠도는 '파일 합체기'중 하나인 Power Merger을 분석해보기로 했다.

 

[프로그램 설명]

 

이 프로그램은 흔히 '섭파 합체기'라고도 불리울만큼 초딩사이에 유행하는 프로그램이다.

정상적으로 보이는 프로그램에 서버파일 혹은 조크바이러스를 삽입하여 사용자가 눈치채지 못하도록 컴퓨터에 바이러스를 심어놓는다.

 

Visual Basic 6.0으로 껍대기만 있는채로 컴파일된 Test.exe와 APILOAD.exe를 합체하여 본체를 만들었다.

 

[합체된 프로그램]

 

 

[분석]

먼저 MSVCRT.__getmainargs와 MSVCRT._acmdln을 통해 CommandLine을 가져온다.

 

그리고 ESI에 CommandLine 문자열의 끝 포인터를 담은 ESI와 ModuleHandle(hInstance)를 담은 EAX를 PUSH하고 401AC0을 CALL한다.

 

그 함수 내부로 들어오게되면 Arg.3(CommandLine의 마지막 포인터)와 OFFSET 004043D8과 stricmp를 통해 비교하게되는데, 호출명령인자가 없을경우 그대로 쭉 진행하게된다.

그대로 진행하게될시, "C:\Users\사용자이름\AppData\Local\Temp\~__UNINST.EXE" 경로에 자기자신을 복사한뒤 ShellExecuteA로 "C:\Users\사용자이름\AppData\Local\Temp\~__UNINST.EXE" 명령인자를 전달하고 종료하게된다.

 

우린 프로그램 내부에 있는 합체된 exe 파일을 분해하는것이 목적이므로, 위 사진의 JNE를 JMP로 고쳐 강제로 명령인자가 전달되었다는 가정 하에 진행하도록 수정시킨다.

 

[JMP로 고친 모습]

 

그럼 신세계가 펼쳐질 것이다.

 

우리가 찾던 APILOAD.exe가 보인다. 그리고 APILOAD.exe와 Test.exe의 파일 크기인 196608과 16384도 보인다.

 

196608이 OFFSET 4040E9에 위치하고 ImageBase가 0x400000즈음에 있는것으로 보아 파일 크기나 파일 이름은 전역변수 혹은 리소스섹션에 저장된것을 알 수 있다. 나중에 분해기를 만들때 유용하게 사용될 변수들이다.

 

함수들을 잘 따라가보면, 부분부분 CALL하는것이 보이는데 스택(지역변수들)에 각종 문자열들을 입력하는 함수들이다.

그리고 마지막으로 CALL하는 부분이 보이는데 따라가보자.

 

 

함수로 들어가게되면 지역변수에 4168Bytes나 할당하는것을 볼수있다.

이것을 통해 Array Of Bytes가 지역변수로 선언된것을 유추할 수 있으며, 이곳에 암호화된 파일을 복호화하는 루틴이 있을것이라 예상 또한 가능하다.

 

 

이부분은 자기 자신을 "C:\Users\사용자이름\AppData\Local\Temp\pmThis.tmp"로 또다시 복제하는 과정이다.

(함수 내부적으로 CopyFile API가 사용된다.)

아마도 자기 자신을 직접 File Streaming API로 다루기 위험해서 복제본을 만들고 그곳으로부터 복호화할 정보를 빼내오는것같다.

(함수를 CALL하는 부분들을 따라가게되면 MFC에 사용된는 함수들이 사용되는걸 볼 수 있는데 MFC.42 함수들은 함수명도 제대로 적혀져 있지 않을뿐더러 API까지 깊숙히 숨겨져서 CALL하게 되어 어떤 과정을 하는지 알아내는 것은 무척 귀찮은 일이다. -_-;;)

 

쭉 내려가다보면
004017E9  0F85 D1000000 JNE 004018C0

이 보이게되는데 따라가보자.

 

다시금 한번 파일 크기를 불러오는 모습이다.


이곳을 잘 보면 ESI에 16384를 담고 EDI에 196608을 담은 뒤 EAX에 파일의 전체 크기를 가져오고 ESI, EDI를 차례대로 뺀다.

그럼 EAX에 남는 값은 0x6000이다.

 

 

이제 어떤 반복문의 한 구문으로 들어오게되는데, CALL MFC42.#5442를 호출하게되면 할당된 스택에 pmthis.tmp의 파일포인터 0x6000부터 0x1000만큼 반복되어 복사되어 들어온다.


00401941  8A4C04 58     MOV CL,BYTE PTR SS:[EAX+ESP+58]
00401945  40                INC EAX
00401946  F6D1            NOT CL
00401948  884C04 57     MOV BYTE PTR SS:[EAX+ESP+57],CL
0040194C 3BC6            CMP EAX,ESI
0040194E 72 F1            JB SHORT 00401941

 

이 반복문 쪼가리가 복호화 루틴이다.

아까 지역변수에 4096bytes만큼 할당된 바이트어레이에 암호화된 파일 정보가 들어왔다.

첫번째 바이트에 NOT 연산을 실행시키면서 한칸한칸 앞으로 이동하며 복호화를 쭉 진행한다.

 

자, 그럼 복호화 루틴도 알아냈으니, 파일 분해기를 제작해보자.

 

아까 파일 이름과 파일 크기의 RVA값을 알아냈으니, RVA TO RAW 공식을 통해 파일상에 어디에 정보가 존재하는지 유추가 가능하다.

 

 

또한 0x6000로부터 암호화된 파일 정보를 뽑아오는것을 볼 수 있었으니, 우리도 파일을 분해할때 이쪽부터 암호화된 exe파일을 빼내오면 될것이다.

 

이것을 Visual Basic 6.0으로 코딩하면 아래와 같다.

 

Private Sub Command1_Click()
On Error GoTo ErrLbe

    Dim Buf(64) As Byte
    Dim FileLen1 As Long, FileLen2 As Long
    Dim FileName1 As String, FileName2 As String
    Dim EnBuf() As Byte, DeBuf() As Byte
   
    Dim FF As Integer

    FF = FreeFile
    Open szPath For Binary As #FF
   
        '### 첫번째 파일 크기를 얻어온다.
        Seek #FF, &H407A
        Get #FF, , Buf
        FileLen1 = atoi(Buf)
       
        '### 첫번째 파일 이름을 얻어온다.
        Seek #FF, &H4226
        Get #FF, , Buf
        FileName1 = GetFileName(Buf)
       
        '### 두번째 파일 크기를 얻어온다.
        Seek #FF, &H40EA
        Get #FF, , Buf
        FileLen2 = atoi(Buf)
       
        '### 두번째 파일 이름을 얻어온다.
        Seek #FF, &H4346
        Get #FF, , Buf
        FileName2 = GetFileName(Buf)
       
        Dim FF2 As Integer, FF3 As Integer
        FF2 = FreeFile: FF3 = FreeFile
        Open DestPath & "\" & FileName2 For Binary Access Write As #2
        Open DestPath & "\" & FileName1 For Binary Access Write As #3
       
            Seek FF, &H6001
           
            ReDim EnBuf(FileLen2 - 1)
            Get FF, , EnBuf
            DeBuf = DecodeSource(EnBuf)
            Put #2, , DeBuf
           
            ReDim EnBuf(FileLen1 - 1)
            Get FF, , EnBuf
            DeBuf = DecodeSource(EnBuf)
            Put #3, , DeBuf
           
        Close #2
        Close #3
       
    Close #FF

    MsgBox "분해에 성공하였습니다.", vbInformation, "Success"

Exit Sub

ErrLbe:
    MsgBox "오류! 분해에 실패하였습니다.", vbCritical, "Error"

End Sub

 

 

적절하게 파일 경로 위치 다이알로그, 폴더 브라우저만 추가하면 완성된다.

[완성본]

 

아까 합체했던 프로그램으로 실험해보기로 하자.

 

분해하기를 누르면

 

원본 프로그램이 추출되는것을 볼 수 있다.