Information


  • File Type : hwp
  • hash : f2e936ff1977d123809d167a2a51cdeb
  • hwp Property Set

  • Process Tree

  • Contents

Analysis


  • hwp 내부에는 EPS가 삽입되어 있음

  • EPS 내부함수의 xor 연산을 통해 쉘코드가 포함된 추가 루틴을 Decode함

  • Decode 된 전문 내부에서 쉘코드를 확인할 수 있음

  • 쉘코드를 분석하기 용이한 exe 형태로 변환

쉘코드 분석_1

  • NOP slide로 시작하는 엔트리포인트 확인할 수 있음(변환전과 동일)

  • XOR 연산을 통해 다음 실행될 루틴을 Decode함

  • CreateProcessA를 통해서 iexplorer.exe 프로세스를 생성함

  • 생성한 프로세스에 악성행위하는 내용 추가를 위해 아래의 API를 호출함

  • WriteProcessMemory 루틴 분석

  • 첫번째 인자인 HANDLE을 확인했을 때 84임을 확인할 수 있고, HANDLE 84의 값은 PID : 674

  • 0x674 = 1,652 이므로, PID 1652 값임을 알 수 있음

  • 두번째 인자인 값인 150000은 iexplorer.exe에 쓸 주소를 나타내고,

  • 세번째 인자의 4014D3 주소의 값을 Write함

  • CreateRemoteThread 루틴 분석

  • lpStartAddresslpParameter 인자로 0x150000(WrtieProcessMemory로 Write한 iexplorer.exe의 내부주소)로 설정되어 있음
  • 해당 API를 통해 프로세스가 suspend 상태에서 resume될 것임을 알 수 있음

첫번째 쉘코드는 iexplrer.exe 를 생성하고 추가 쉘코드를 Write 함으로써 악성행위를 수행

쉘코드 분석_2

  • LoadLibray API를 통해 wininet.dll 함수를 로드함

  • 이후 인자로 아래 URL을 인자로 주고 GetProcAddreass를 통해 wininet.dll dll의 InternetOpenUrlA API를 리턴함

두번째 쉘코드는 지정된 URL에 접속시도하고, 추가 파일을 다운로드하여 추가 악성행위 실행

  • 현재, C&C 서버는 닫혀있음


1. Overview


 

원격 서버의 소스를 편리하게 작업할 수 있는 VScode "Remote VScode"를 통해 작업할 경우 원격 서버의 코드 파일이 로컬 드라이브에 저장된다.

 

 

 

2. Body


 

코드가 저장되는 경로는 다음과 같다.

C:\Users\[UserName]\AppData\Local\Temp\[랜덤명]\[remote_server_path]

 

[그림 1] 저장된 소스파일

 

 

3. Conclusion


 

당연한 사항이지만 사용자 입장에서 코드가 저장되는 사실을 인지해야하고 저장되는 경로를 파악하고 있어야 한다고 생각한다.

 

 

'개발 > Setting' 카테고리의 다른 글

VScode remote development environment settings (with rmate)  (0) 2019.04.24

1. Overview


본 게시글은 Windows 10 Pro (버전 1809) x64 에서 실행되는 Powershell을 대상으로 기록하였습니다. Windows OS 의 버전이나 사용자의 세팅 환경에 따라 다를 수 있음을 알려드립니다.

 

 

 

1.1 문제의 발견

 

서버의 원격 개발을 위해 VScode의 ssh 연결을 위해 {시작 - 실행}을 통해 Powershell을 입력하여 호출하였다.

[그림 1] 실행을 통한 powershell 호출

 

평소 Powershell을 "CMD"와 유사하게 설정해놓고 사용하고 있다.

[그림 2] CMD와 유사한 Powershell 세팅

 

Windows에서는 {시작 - 실행}으로 Powershell을 실행하는 방법 이외에 다른 방법으로 호출할 수 있도록 지원한다. 

설정(Windows Shortcut : Winkey + i)에서 {개인설정 - 작업표시줄}의 아래 그림에 표시된 토글 버튼의 활성화 여부에 따라 파워유저 메뉴(Windows Shortcut : Winkey + x or 시작버튼 우클릭) 에서 Powershell을 호출할 수 있다.

[그림 3] 개인설정 - 작업 표시줄의 설정

 

해당 토글의 활성화를 통해 파워유저 메뉴에서 Powershell을 실행할 수 있다.

[그림 4] 파워유저 메뉴의 Powershell

 

파워유저 메뉴를 통해 실행한 Powershell과 실행을 통해 실행한 Powershell이 다른 것을 확인할 수 있었다.

같은 Powershell인데 하나는 설정이 적용되어 있고 하나는 기본 설정으로 되어 있는 것을 확인하였다.

[그림 5] 서로 상이한 powershell

 

 

 

2. Body


2.1 파워유저 메뉴의 Path

 

앞서 등장한 {Winkey + i}를 통해 실행할 수 있는 파워유저 메뉴는 아래의 경로에서 관리된다.

C:\Users\[USERNAME]\AppData\Local\Microsoft\Windows\WinX

 

 

{시작 - 실행}을 통해 호출하는 명령은 다음과 같다.

%localappdata%\Microsoft\windows\winX

 

 

파워유저 메뉴의 각 콘텐츠를 관리하는 레지스트리는 다음과 같다.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\InboxApp

 

 

해당 경로를 통해 확인한 결과 파워유저 메뉴는 "Group1~3"으로 관리되고 있었다[1].

[그림 6] 파워유저 메뉴와 Group1~3 폴더

 

 

Group1~3 폴더 내부에는 바로가기 파일들이 존재하며 파워유저를 통해 실행하는 각 기능들은 바로가기를 통해 호출되고 있음을 알 수 있다.

[그림 7] Group1과 Group2의 파워유저 메뉴

 

 

[그림 8] Group3과 파워유저 메뉴

 

 

 

2.2 서로 다른 Powershell 실행의 비교

 

{시작 - 실행}을 통한 Powershell의 실행은 다음 경로의 "powershell.exe"를 실행한다.

C:\Windows\System32\WindowsPowerShell\v1.0

 

파워유저 메뉴를 통한 Powershell의 실행은 다음 경로의 "powershell.exe"의 바로가기를 통해 실행한다.

C:\Users\[UserName]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell

 

이는 시작에서 검색하여 실행한 경우와 동일한 경로이다.

[그림 9] 시작을 통해 검색한 Powershell

 

 

"C:\Users\[UserName]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell" 경로의 Powershell의 속성을 확인해보면 다음 그림과 같다.

[그림 10] Start menu의 Powershell 속성

 

 

해당 start menu의 Powershell은 "C:\Windows\System32\WindowsPowerShell\v1.0" 경로의 Powershell이다.

그렇다면, 동일 파일임에도 불구하고 다른 이유는 무엇일까?

 

그 이유는 바로가기의 속성에서 찾을 수 있었다.

바로가기의 속성에서도 색, 글꼴등을 설정할 수 있다.

[그림 11] 바로가기 파일의 속성창

 

 

Windows 10 OS가 설치될 때 시작 프로그램 경로에 Powershell의 바로가기가 생성되고, 해당 바로가기는 설치 당시의 Powershell의 디폴트 세팅으로 생성되었기 때문에 기존 디폴트 세팅으로 되어 있음을 추측할 수 있다.

 

 

그렇다면, 변경된 Powershell의 속성이 저장된 powershell을 바로가기로 만들면 어떤 결과를 출력할까?

[그림 12] 속성이 변경된 Powershell의 바로가기 결과

 

 

예상대로 기존에 설정된 파일의 바로가기를 생성하면 해당 파일의 속성이 따라오는것을 확인할 수 있다. (폰트는 아닌듯 하다.)

 

 

 

3. Additional Information


3.1 파워유저 메뉴의 Powershell이 Start Menu에서 실행되는것은 어떻게 확인할 수 있을까?

 

단순하게 Start Menu에 있는 powershell의 파일명을 살짝만 변경하면 된다. "powershell2"로 파일명을 변경한 후 파워유저 메뉴의 powershell을 실행해보았다.

 

[그림 13] 파일명 변경 후 파워유저 메뉴를 통해 실행한 powershell

 

 

파일명을 변경한 후에도 시작을 통한 검색에서는 변경된 파일명으로 정상적으로 검색되며 실행 또한 정상적이다.

[그림 14] 파일명 변경 후 시작을 통해 검색한 powershell

 

 

또한 Start Menu에서 Powershell가 여러개 존재할 경우에 하나만 검색 결과로 표출된다. 숫자의 경우 낮은 숫자가 표출된다.

해당 폴더에는 powershell2와 powershell3이 존재했지만 powershell3은 검색결과에 표시되지 않았다.

[그림 15] powershell3 검색 결과 확인

 

 

[그림 16] Start Menu의 powershell2와 powershell3

 

 

 

3.2 파워유저 메뉴 활용

 

파워유저 메뉴를 편리하게 활용하기 위한 도구가 제공된다. "win+x menu editor" 도구가 있으며 관심이 있다면 찾아보면 좋을것 같다.

 

이외에도 파워유저 메뉴에 원하는 프로그램을 추가할 수 있는 다양한 방법이 있으니 관심이 있다면 참고문헌을 통해 찾아보는것을 추천한다.

 

 

 

4. Conclusion


{시작 - 실행}을 통해 실행한 Powershell과 파워유저 메뉴를 통해 실행한 Powershell이 설정이 다른것을 확인하고 같은 Powershell 사이에 어떤 차이가 있는지 확인하였다.

 

결론은 같은 Powershell이지만 바로가기의 속성에서의 사용자 변경사항 적용 유무의 차이가 있었다. 

 

큰 통찰력을 주는 결론은 아니지만 파워유저 메뉴에 대해 알아볼 수 있는 좋은 기회였다고 생각한다.

 

 

 

5. References


[1] "https://www.interfacett.com/blogs/modify-winx-menu-windows-10"

[2] "https://www.htguk.com/get-back-control-panel-winx-menu-instead-settings-windows-10-creators-update-customize-way-really/"

1. Overview


 

VScode를 활용하면 원격 서버의 환경을 그대로 활용하여 로컬환경에서 개발할 수 있다.

본 게시글은 VScode를 활용하여 rmate를 세팅하는 방법에 대해 기록하였다. 기본적인 세팅은 References의 블로그를 참고하였다[1][2].

 

 

2. Body


 

세팅에 필요한 순서는 다음과 같다.

  1. VScode 환경 세팅 (로컬)
    • "Remote VScode" 확장 프로그램
    • "Remote.Onestartup" : True 세팅
  2. Rmate 설치 (서버)
  3. Trouble Shoothing (번외)

 

 

2.1 VScode 환경세팅

Vscode의 Extensions 탭에서 "Remote VScode"를 검색하여 설치한다. (Windows Shortcut : Ctrl + Shift + X)

[그림 1] "Remote VScode" 확장 프로그램 설치

 

설치가 완료된 후 VScode의 설정을 수정한다. (Windows Shortcut : Ctrl + ,)

(File -> Preferences -> Settings)

설정 화면 호출 후 "Remote" 검색하여 "Remote:Onestartup" 하단 메뉴를 체크한다.

[그림 2] "Remote:Onestartup" 세팅

 

 

 

2.2 Rmate 설치

서버에서의 Rmate 설치는 References에 기록한 블로그의 명령어를 활용하였다.
입력한 명령어는 다음과 같다.

$wget https://raw.githubusercontent.com/sclukey/rmate-python/master/bin/rmate
...
$chmod +x ./rmate
$mv ./rmate /usr/local/bin/rmate

 

 

 

2.3 접속

접속은 로컬 환경에서의 PowerShell을 통해 명령어를 입력하여 쉽게 접속할 수 있다.

접속에 필요한 명령은 다음과 같다. ssh 포트를 변경했을 경우 "-p" 이후의 명령을 입력하면 된다.
ssh -R 52698:127.0.0.1:52698 [Remote_Server_User]@[Remote_Server_Address] -p [Port num]

 

ssh 접속이 완료된 상태에서 작업할 파일명을 아래의 명령어 형식에 맞게 입력한다.
rmate -p 52698 [/경로/파일명.py]

 

 

 

3. Trouble Shoothing


간단한 과정이지만 중간중간 문제가 발생한 사항은 다음과 같다.

 

  1. Couldn't connect to TextMate!
  2. Exception: Could not connect to textmate : Connection refused

 

 

3.1 Couldn't connect to TextMate!

해당 문제는 한 로컬에서 ssh 를 2개 이상 접속하고 rmate 명령어를 작성했을 때 출력되는 에러이다. 해당 문제는 호출 되어 있는 여러개의 ssh를 하나만 남겨놓고 종료하고 다음 과정을 수행하면 해결할 수 있다.

 

 

Vscode에서 F1을 누른 후 Remote:Stop Server를 통해 서버를 정지하고 Remote:Start Server 를 통해 재실행한다.

[그림 3] "Couldn't connect to TextMate!" 문제 해결[3]

 

 

 

3.2 Exception: Could not connect to textmate : Connection refused

해당 문제는 로컬에서 ssh 접속 과정에서 "127.0.0.1"을 "localhost"로 입력하였을 때 발생한다. 해결 방법은 단순히 "127.0.0.1" 을 사용하면 된다.

[그림 4] "Exception: Could not connect to textmate : Connection refused" 문제 해결[4]

 

 

4. Conclusion


본 게시글에서는 VScode를 통해 원격 개발 환경을 세팅하는 과정을 기록하였다.

이를 통해 VScode를 에디터로 사용하는 사용자들에게 편리함을 줄 수 있을 것으로 기대한다.

 

 

 

5. References


[1] https://thrillfighter.tistory.com/458

[2] https://mj-youn.github.io/2018/10/12/VSCode-Remote-File-edit/

[3] "Couldn't connect to TextMate!", https://github.com/sclukey/rmate-python/issues/2

[4] "When attempting to open files via rmate file never opens", https://github.com/rafaelmaiolla/remote-vscode/issues/55

'개발 > Setting' 카테고리의 다른 글

VScode rmate 작업시 Temp 파일 저장 확인  (0) 2019.04.25

1. Overview



Python을 사용하여 'HWP Parser' 제작중 BinData의 내부 Stream에 대해 Decompress를 수행하던 도중 발생한 Trouble에 대해 서술한다.


2. Structure



HWP File Format에 관련하여 한컴 오피스는 홈페이지를 통해 공식 문서를 제공한다.


그 중 BinData 스토리지에는 그림이나 OLE 개체와 같이 문서에 첨부된 바이너리 데이터가 각각의 스트림으로 저장된다.


Parser 제작 과정에서 해당 한글 문서 파일의 악성 유무 판별을 위해 Decompress를 수행해야 했다.


[그림 1] BinData Area



Decompress에는 Python zlib을 활용하였다. 보편적인 zlib의 Decompress 구문은 다음과 같은 에러를 출력했다.


zlib.error: Error -3 while decompressing data: incorrect header check


[그림 2] 에러 확인


3. Trouble Shooting



문제해결을 위해 검색 도중 다음과 같은 글을 확인할 수 있었다.


글에 따르면 메모리에 저장할 수 있는 크기를 초과하는 Stream (또는 파일 입력) 크기 문제로 인해 위의 에러가 발생했을 것이라고 한다. 실제 메모리 크기를 초과한 것이 아닌 버퍼 기본 크기를 초과했기 때문이다.


이를 해결하기 위한 방법은 Stream을 버퍼링으로 처리하고 Decompress를 수행하는 방법이 존재한다. 함께 제공된 솔루션 소스코드는 다음과 같다[1].

 
import zlib
f_in = open('my_data.zz', 'rb')
comp_data = f_in.read()
zobj = zlib.decompressojb()  # obj for decompressing data streams that won’t fit into memory at once.
data = zobj.decompress(comp_data)


위의 방법과 같이 버퍼링을 적용하고 테스트를 진행했을 때 또 다시 동일한 에러가 뜨는 것을 확인했다.


조금 더 찾아보던 도중 다음과 같은 글을 찾을 수 있었다.


[그림 3] wbit 관련 솔루션[2]



위 글에서는 wbit 옵션을 -15로 정의하면 에러가 해결된다고 제시했다. zlib 모듈 공식 홈페이지에서 제공하는 문서에 따르면 WBITS의 의미는 다음과 같다.


[표 1] MAX_WBITS의 의미[3]

The wbits argument controls the size of the history buffer (or the “window size”) used when compressing data, and whether a header and trailer is included in the output. It can take several ranges of values, defaulting to 15 (MAX_WBITS):

  • +9 to +15: The base-two logarithm of the window size, which therefore ranges between 512 and 32768. Larger values produce better compression at the expense of greater memory usage. The resulting output will include a zlib-specific header and trailer.
  • −9 to −15: Uses the absolute value of wbits as the window size logarithm, while producing a raw output stream with no header or trailing checksum.
  • +25 to +31 = 16 + (9 to 15): Uses the low 4 bits of the value as the window size logarithm, while including a basic gzip header and trailing checksum in the output.


MAX_WBIS 값은 15를 가지며 이를 -로 선언하면 -15 값으로 정의되기 때문에 에러를 해결할 수 있다.


이를 적용한 소스코드는 다음과 같다.


 
def bin_data(ole,bin_list):
    print ()
    print ('[+] BinData Information')
    for content in bin_list:
        if content[0] == 'BinData':
            print ('   - File Name : %s' %content[0]+'/'+content[1])
            bin_text = ole.openstream(content[0]+'/'+content[1])
            print ('   - File Size : %s' %ole.get_size(content[0]+'/'+content[1]))
            data2 = bin_text.read()
            print ('   - Hex data ~20bytes(pre-Decompress) : %s' %data2[:20])
            zobj = zlib.decompressobj(-zlib.MAX_WBITS)
            data3 = zobj.decompress(data2)
            print ('   - Hex data ~20bytes(Decompress) : %s' %data3[:20])
            f = open('./'+content[1]+'_Decom.txt','wb')
            f.write(data3)
            f.close
            print ()


결과는 다음과 같다.



[그림 4] 정상적으로 Decompress 완료된 Stream



4. References



[1] https://stackoverflow.com/questions/32367005/zlib-error-error-5-while-decompressing-data-incomplete-or-truncated-stream-in?rq=1


[2] https://daehee87.tistory.com/m/508?category=404227


[3] https://docs.python.org/3/library/zlib.html

+ Recent posts