2016. 11. 27. 20:21 :: 웹 보안

안녕하세요 Message입니다.

오늘의 포스팅 주제는, 예전에 마주쳤을때 당황했었던 해시뱅(HashBang, #!)에 대해 다루고자 합니다.

해시뱅에 대해 개념부터 장단점, 개인의 의견이 잘 포스팅되어 있는 블로그가 있습니다.

https://blog.outsider.ne.kr/698  : 해시뱅(#!)에 대해서... 

 

하지만 저는 개발자가 아니므로.. 해시뱅을 다뤄본 경험이 없기 때문에

초보 분석가가 해시뱅을 바라보는 시각에서 포스팅을 진행했습니다.

 

 

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

1. 해시뱅(HashBang, #!) 이란?

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

 

처음 해시뱅을 맞딱뜨렸을때는 무엇으로 검색해야 할지 몰라서 헤메었습니다.

정확한 URL을 알고싶은데, URL을 모르게 하기 위해서 보안처리가 잘되있는건가? 싶기도 했었고

고민하다보니 시간이 흘러가고..결국 그것이 무엇인지도 모른채 바쁜 맘에 그냥 지나쳤습니다.

 

금강산도 식후경이라고 일단 해시뱅이 어떻게 생겼나 보고 넘어갑시다.

해시뱅은 URL에서 발견할 수 있는 특수문자 "#!" 입니다. 말그대로 해시(#) + 뱅(!) 이지요.

검색해보니 국내 유명 웹사이트 중에서 해시뱅을 사용하는 곳은 트위터, 밴드 정도가 있지만,

트위터의 경우 논란이 많아 2012년 이후로는 더이상 해시뱅을 쓰지 않는것으로 보입니다.

 

 

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

2. 어디에 쓰는 물건(?)인고

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

 

해시뱅을 쓰는 이유는 웹어플리케이션을 제작할때 싱글 페이지 어플리케이션(SPA) 스타일로 구성하기 위함입니다.

메인 화면이 로딩된 이후에는, 페이지의 갱신 없이 URL을 변경하기 위해서 사용됩니다.

자바스립트를 이용하여 화면을 빠르게 변경해줌으로서 리소스를 줄이는것이 목적이죠.

 

저는 이러한 부분이 처음에 잘 이해가 되지 않았습니다.

하지만 안드로이드 앱을 개발하면서 프래그먼트를 사용한적이 있었는데,

해시뱅에서 "#" 뒤에 나오는 "!" 이후의 부분을 Fragment Identifier 라고 부르는것을 보고 조금은 이해가 되었습니다.

안드로이드의 프래그먼트는 비교적 리소스가 큰 액티비티로 모든 화면을 구성하지 않고,

하나의 액티비티 안에서 여러개의 Fragment로 화면을 구성하여 UI에 소요되는 작업량을 감소시키는 역할이니까요.

아래 예제는 소스코드를 확인할순 없지만, 하나의 Activity안에 여러 Fragment가 슬라이딩 되는 구조일겁니다.

 

 

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

3. 해시뱅의 문법..?

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

 

해시뱅의 왜 쓰이는지 알아봤습니다.

그렇다면 이제는 어떤 방식으로 동작하는지 알아봅니다.

 

1. 네임앵커를 이용한 화면 이동

해시뱅은 HTML의 네임앵커 라는 기능을 이용한다고 합니다.

어떤 특정 위치에 책갈피를 지정하고, 그 지정된 곳으로 이동하는 것을 네임앵커라고 합니다.

 

예를들면,

<label name="anchor"> 여기로 이동 </label> 으로 단순 텍스트에 name 태그를 "anchor"로 지정해주고,

<a href="#anchor"> 클릭하면 </a> 으로 링크를 지정해놓으면, 클릭했을 때 name 값이 "anchor"인 곳으로 이동합니다.

아래 사이트에서 네임 앵커를 심플하게 체험할 수 있게 페이지를 구성해놓으셨더군요.

URL : http://mytory.net/archives/229#there

 

해시뱅은 위의 네임앵커 기능을 이용하여 "#" 뒤에 오는 Fragment를 마치 URL스럽게 구성을 합니다.

예를 들면 이렇게 말이죠 → <label name="!/tistory/url">

일반적으로 해시뱅을 구성할때 "#!" 이라고 쓰기 때문에 해시뱅이라고 불린다고 하네요.

 

 

2. 구글과 해시뱅, 모르면 찜찜

해시뱅이 적용된 HTML을 살펴보면, 공통점이 있습니다.

바로 exec, IndexOf, hasOwnProperty 함수등을 이용하여

URL 안에 "_escaped_fragment_=" 문자열과 일치하는 부분이 있는지 검색하는 부분입니다.

아마 해시뱅의 배경에 대해서 미리 알고 있지 않으면 이게 무슨 소린가 할만한 내용입니다.

 

이유는 구글때문입니다.

구글의 크롤러는 SPA를 검색할때 느낌표(!)가 있는지 체크합니다.

이후에 해시뱅 부분을 "_escaped_fragment_=" 문자열로 대체합니다.

대체된 새로운 URL을 이용하여 다시 서버로 요청합니다.

따라서 구글의 검색엔진에 잘 노출되기 위해서는 이와 같은 구글 크롤러의 요청에 대응을 해야합니다.

따라서 위의 소스코드들에서 공통적인 로직이 존재하게 되는것이죠.

 

해당내용에 대해 더 자세하게 보실분은 아래 블로그를 참고하세요.

싱글 페이지 어플리케이션에서의 검색 엔진 최적화 (SEO) : http://funnygangstar.tistory.com/183

 

 

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

4. 마무리

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

 

해시뱅이 국내에서 많이 사용되지 않다보니 마주칠 일이 별로 없을지도 모르겠습니다만...

덕분에 SPA나 HTML에 대해서 살펴볼 좋은 기회였습니다.

 

해시뱅의 문제점이나 장/단점에 대해서는 다루지 않았습니다.

개발보다는 웹페이지 분석 + 취약점 진단 측면에서 알고 있으면 좋은 배경지식만 간략하게 살펴보았습니다.

잘못된 점이나 문제가 될만한 부분은 댓글 남겨주시면 수정/조치 하겠습니다.

감사합니다.

 

 

posted By Message.

Commit your way to the LORD, trust in him and he will do this. [PSALms 37:5]

posted by Red_Message
2016. 11. 9. 21:00 :: 문제풀이/WebHacking,kr

안녕하세요. Message입니다.

Webhacking.kr Lv9 문제풀이입니다. 

 

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

1. 문제분석

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

 

1) 살펴보기

9번 문제에 접속합니다. 점수는 무려 900점...

숫자 1, 2, 3 과 password 쿼리전송 버튼이 존재하는 페이지가 나옵니다.

다른분들의 풀이를 보니, ID/PW 입력 인증창이 별도로 뜨면서 Method를 이용하여 우회해야 볼 수 있는 화면인데

바로 뜨는거 보니...수정되었나봅니다.

 

각 번호를 클릭하면 각 아래의 화면이 나타납니다.

페이지 넘버 3에서 "Secret" 이라는 문구와 함께 hint가 주어졌습니다.

length = 11, 그리고 column명 2개(id, no) 입니다.

  

 

또한 이것저것 특수문자도 넣어보고, 각종 쿼리문을 날려보았더니

아래와 같은 "Access Denied" 문구가 뜹니다. 특정 문자가 필터링되고 있음을 알 수 있습니다.

 

2) 문제 의도파악

처음에는 "Apple", "Banana"가 ID값이라는 표시가 없어서 페이지들의 목적이나 의미에 대해서 헷갈렸습니다.

결국 다른 풀이들을 찾아본 후에야 저 과일이름들이 ID값이라는걸 알게되었죠..

예를들어 no=1 일때의 ID값은 "Apple", no=2 일때의 ID값은 "Banana",

no=3 일때의 ID값은 알려주지 않으므로 우리가 알아내야할 값은 no=3일대의 ID값인듯 합니다.

 

 

 

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

2. 문제풀이

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

 

0) 아파치 웹인증 우회

아파치 웹인증이 나오진 않았지만, 공부하는데 초점이 맞춰져 있으므로 간략하게 짚고 넘어갑니다.

만약 정상적으로 인증창이 나왔다면 아래와 비슷한 창이 나타났을겁니다.

 

이러한 인증은 아파치 서버에서 .htaccess 파일을 이용한 인증을 사용할 경우 나타나는 창으로서,

.htaccess 파일을 이용한 인증을 이용하기 위해서는 httpd.conf 파일에 AllowOverride 설정을 해줘야 합니다.

 <Directory "/var/www/html">

...

AllowOverride AuthConfig

...

 </Directory>

 

설정이 완료되면 .htaccess 파일 내부에 Limit 옵션으로 인증에 적용될 메소드를 기재하게 됩니다.

아래와 같이 설정을 하게 된다면, GET과 POST로 요청이 들어올 경우 아파치 웹인증이 동작합니다.

 AuthName  "~~~"

 AuthType   Basic

 AuthUserFile "~~~~/.htpasswd"

 <Limit GET POST>

requre valid-user

 </Limit>

 

하지만, 만약 관리자가 옵션을 적는 방법을 헷갈리거나, 단순히 GET과 POST 등 일부 메소드만 설정한다면

다른 메소드로 접근하여 인증이 우회되는 상황이 발생합니다.

테스트는 못해봤지만, 아래와 같이 OPTIONS 등의 메소드로 패킷을 보내면 해당 인증창은 무시되고 다음 단계로 넘어갑니다.

 

 

1) 이용할것

일단 주어진 힌트를 살펴봅니다. 만약 ID를 구하는것이 맞다면,

힌트가 의미하는바는 ID의 길이가 11자리이며, 테이블의 컬럼은 id, no 이라는 뜻일겁니다.

 

힌트와 쿼리문을 입력하는 칸을 보니 느낌적으로 Blind SQL 공격을 시도하는게 맞는것 같습니다.

그래서 예전 Blind SQL을 사용했던 2번 문제를 살펴보니 

2번 문제는 Time 주석문을 이용하여 Blind SQL의 결과를 알아내는 케이스였습니다. (아래와 같이요)

하지만 이번 문제는 no, pw 변수에 이것저것 넣어봐도 True/False를 체크할만한 수단이 없어보입니다.

2번문제 링크 : http://redscreen.tistory.com/87

 

어떤식으로 Blind SQL의 성공여부를 알 수 있는지 검색해보니 

MYSQL 쿼리문에서 SELECT문에 IF문을 결합하여 사용하는 방법이 있더군요.

아래는 APMSETUP에서 테스트용으로 IF문과 SUBSTR 함수를 결합하여 사용한 예시입니다.

그렇다면 IF문은 이번 문제에서 어떻게 사용해야 하는걸까요?

 

현재 문제를 풀이하고 있는 페이지는 index.php 입니다.

그리고 no 값에 따라서 보여지는 글자가 달라집니다. 즉, 다른 페이지에 넘어가는게 아니라

입력해주는 no에 따라서 DB에서 ID값을 가져오는 메커니즘으로 추측됩니다.

그렇다면 "SELECT id FROM no = OO" 정도가 되지 않을까요?

여기에 IF문을 아래와 같은 방식으로 적용한다면 우리가 원하는 값을 불러올 수 있습니다.

 SELECT id FROM 테이블명 WHERE no = IF(substr(id, 1, 1) = 0x41, 3, 0)

 

이를 검증하기 위해 테이블에 세가지 튜플을 넣고 테스트합니다.

① (1, Apple)  ② (2, Banana)  ③ (3, aaaaaaaaaaa) / 11자리

 

이후에 위와 같은 쿼리를 날리면 아래와 같은 결과를 얻을 수 있습니다.

 ①번 튜플 : (1, apple )

    - 첫번째 문자 'A' 와 0x41 일치 → no=3 반환 

    - 완성쿼리 : SELECT id FROM lv9 WHERE no=3 : ①번 튜플은 no=1 이므로 출력 NO

 ②번 튜플 : (2, Banana)

    - 첫번째 문자 'B' 와 0x41 불일치 → no=0 반환

    - 완성쿼리 : SELECT id FROM lv9 WHERE no=0 : 번 튜플은 no=2 이므로 출력 NO

 ③번 튜플 : (3, AAAAAAAAAAA)

    - 첫번째 문자 'A' 와 0x41 일치 → no=3 반환 

    - 완성쿼리 : SELECT id FROM lv9 WHERE no=3 : ③번 튜플은 no=3 이므로 출력 YES

 

 

2) 필터링 문자 파악

버프슈트의 Intruder 기능을 이용하여 특수문자 필터링을 파악합니다.

엑셀등에서 복사하여 Paste 버튼을 누르면 편리하게 페이로드 추가가 가능합니다.

Length 448 결과값이 "Access Denied" 응답입니다.

위의 쿼리에서 작성한 쿼리에서 "=", "if", "%20" 등이 필터링되고 있습니다.

 

 

 

3) 공격시도

위에서 작성한 쿼리는 아래와 같습니다.

필터링 되는 문자를 파악했으니 뜯어고쳐야 합니다.

 SELECT id FROM 테이블명 WHERE no = IF(substr(id, 1, 1) = 0x41, 3, 0)

 

문자 "=" 을 사용하지 못하므로 strcmp 함수로 대체합니다.

다른분의 풀이를 보니 LIKE로 대체하신분도 계십니다. 저의 경우 strcmp가 더 손에 익어서 선택했습니다.

strcmp 함수는 문자열이 동일한 경우 0을 반환하므로, IF문의 True/False 순서도 바뀌어야 합니다.

 SELECT id FROM 테이블명 WHERE no = IF(strcmp(substr(id, 1, 1), 0x41), 0, 3)

 

또한 %20 이 필터링 되므로, 공백을 제거해야합니다.

 SELECT id FROM 테이블명 WHERE no = IF(strcmp(substr(id,1,1),0x41),0,3)

 

문제에 테스트해봅니다. 결과는 Secret 입니다.

URL : (생략)../web-09/?no=IF(strcmp(substr(id,1,1),0x41),0,3)

 

테스트 완료된 쿼리를 이용한 파이썬 스크립트로 공격을 시도하면 성공입니다.

0x41 부터 시작할 경우 ID값이 대문자로 출력되는데, 아마 8번 문제처럼 자동으로 소문자화 시켜주는 코드가 있을듯 합니다.

하지만 패스워드에 입력할 시에는 소문자로 입력해야합니다.

 

 

 

By Red_Message.

 

posted by Red_Message
2016. 11. 7. 03:29 :: 리버싱

Chapter 06 악성코드

Section 01 악성코드

- 제작자가 의도적으로 사용자에게 피해를 주고자 만든 모든 악의적 목적을 가진 프로그램 및 매크로, 스크립트 등 컴퓨터 상에서 작동하는 모든 실행 가능한 형태

 

1. 악성코드의 분류

가. 악성코드의 분류

이름(코드) 

설명 

바이러스 

- 사용자 컴퓨터(네트워크로 공유된 컴퓨터 포함) 내에서 사용자 몰래 프로그램이나 실행 가능한 부분을 변형해 자신 또는 자신의 변형을 복사하는 프로그램

- 가장 큰 특성은 복제와 감염

- 네트워크의 컴퓨터로 스스로 전파되지는 않음 

웜 

- 인터넷 또는 네트워크를 통해서 컴퓨터에서 전파되는 악성 프로그램

- 윈도우의 취약점 또는 응용 프로그램의 취약점을 이용하거나 이메일이나 공유 폴더를 통해 전파, 최든에는 공유 프로그램(P2P)을 이용하여 전파되기도 한다.

- 바이러스와 달리 스스로 전파되는 특성 

트로이 목마 

- 바이러스나 웜처럼 컴퓨터에 직접적인 피해를 주지는 않지만, 악의적인 공격자가 컴퓨터에 침투하여 사용자의 컴퓨터를 조종할 수 있는 프로그램

- 고의적으로 만들어졌다는 점에서 프로그래머의 실수인 버그와는 다름

- 자시 자신을 다른 파일에 복사하지 않는다는 점에서 바이러스와 구별 

인터넷 악성코드 

- 인가되지 않은 성인 사이트나 크랙 사이트 등에 접속할 때 감염

- 예전에는 인터넷 악성코드로 끝나는 경우가 많았으나 최근에는 웜의 형태로 전이되고 있다. 

스파이웨어 

- 자신이 설치된 시스템의 정보를 원격지의 특정한 서버에 주기적으로 보내는 프로그램

- 사용자가 주로 방문하는 사이트, 검새어 등 취향을 파악하기 위한 것도 있지만 패스워드 등과 같은 특정 정보를 원격지에 보내는 스파이웨어도 존재 


나. 악성 프로그램으로 인해 발생할 수 있는 증상

대분류 

소분류 

설명 

시스템 관련

시스템 설정 정보 변경 

변경 레지스트리 키 값을 변경하여 시스템의 정보를 변경

FAT 파괴 

시스템의 파일 시스템을 파괴 

CMOS 변경 

CMOS 내용을 변경하여 부팅 때 에러를 발생시킴 

CMOS 정보 파괴 

CMOS의 일부를 파괴 

기본 메모리 감소 

시스템의 기본 메모리를 줄인다. 

시스템 속도 저하 

시스템의 속도를 저하시킨다. 

프로그램 자동 실행 

레지스트리 값을 변경해 시스템을 부팅할 때 특정 프로그램을 자동으로 실행 

프로세스 종료 

특정 프로세스를 강제로 종료 

시스템 재부팅 

시스템을 재부팅 

네트워크 관련 

메일 발송 

특정 사용자에게 메일을 발송

정보 유출 

사용자의 정보를 네트워크를 통해서 공격자로 전송 

네트워크 속도 저하 

감염된 컴퓨터가 속한 네트워크가 느려짐 

메시지 전송 

메시지를 네트워크를 통해 다른 컴퓨터로 전송 

특정 포트 오픈 

특정 백도어 포트를 연다 

하드 디스크 관련 

하드 디스크 포맷 

하드 디스크를 포맷 

부트 섹터 파괴 

하드 디스크의 특정 ㅂ분을 파괴 

파일 관련 

파일 생성 

특정 파일(주로 백도어 파일)을 생성 

파일 삭제 

특정 파일이나 디렉터리를 삭제 

파일 감염 

바이러스가 특정 파일을 감염 

파일 손상 

바이러스가 특정 파일에 겹쳐 쓰기 형태로 감염되면 파일이 손상된다. 

특이 증상 

이상 화면 출력 

출력 화면에 특정 내용이 나타남 

특정음 

발생 컴퓨터에서 특정음이 발생 

메시지 상자 출력 

화면에 특정 메시지 상자가 나타남 

증상 없음 

특이한 증상 없음 



Section 02 바이러스

1. 1세대 : 원시형 바이러스

가. 부트 바이러스

- 플로피 디스크나 하디 디스크의 부트 섹터에 감염되는 바이러스로 MBR과 함께 PC 메모리에 저장

- 부팅할 때 자동으로 동작하여 부팅 후에 사용되는 모든 프로그램을 감염시킨다.

- 컴퓨터의 부팅 순서

■ 1단계 : POST

- POST(Power On Self Test)는 운영체제와 관련 있는 부분은 아님. 설치할때 하드웨어 자체가 시스템에 문제가 없는지 기본 사항을 스스로 체크하는 과정이다.

- BIOS(Basin Input/Outpur System)에 의해 실행

■ 2단게 : CMOS

- CMOS(Complementary Metal-Oxicle Semiconductor)에서는 기본 장치에 대한 설정과 부팅 순서를 설정할 수 있으며 BIOS는 CMOS에서 이런 기본 설정 사항을 읽어 시스템에 적용한다.

■ 3단계 : 운영체제 위치 정보 로드

- 윈도우 2003 이전 : 마스터 부트 레코드(MBr : Master Boot Record) 정보를 읽음. CMOS 정보를 읽어 부팅 매체를 확인할 뒤에는 부팅 매체의 MBR 정보를 읽는다.

- MBR은 운영체제가 어디에, 어떻게 위치해 있는지를 식별하여 컴퓨터의 주 기억장치에 적재될 수 있도록 하기 위한 정보

- 하드디스크나 디스켓의 첫 번째 섹터에 저장되어 있다.

- 메모리에 적재될 운영체제가 저장된 파티션의 부트 섹터 레코드를 읽을 수 있는 프로그램(부트 섹터 레코드는 운영체제의 나머지 부분을 메모리에 적재시키는 프로그램을 담고 있다.)


- 윈도우 2008 이후 : 윈도우 부트 서브 시스템(Window Boot Manager)이 실행됨.

- MBR에서 NTLDR이 실행되지 않고, 윈도우 부트 서브시스템이 실행된다. 윈도우 부트 서브 시스템은 bootmgr.exe가 실행되고 부트 설정 데이터(BCD, Boot Configuration Data)를 읽어 실행 가능한 운영체제의 목록을 보여주는데, 이것은 NTLDR이 boot.ini을 읽어 실행 가능한 운영체제의 목록을 보여주는 것과 같다.

- 부트 바이러스는 바로 이 3단계에서 동작.

- 과거 부트 바이러스에 감염된 플로피 디스크로 운영체제를 구동시키면 바이러스가 MBR과 함께 PC메모리에 저장되고 부팅 후에 사용되는 모든 프로그램에 자신을 감염시킨다.

- 부트 바이러스의 종류로는 브레인, 몽키, 미켈란젤로 바이러스가 있다.


나. 파일 바이러스

- 파일을 직접 감염시키는 바이러스.

- 바이러스에 감염된 실행 파일이 실행될 때 바이러스 코드를 실행한다.

- 프로그램을 덮어쓰는 경우, 프로그램 앞부분에 실행 코드를 붙이는 경우, 프로그램의 뒷부분에 코드를 붙이는 경우가 있다.

- 파일 바이러스에는 예루살렘 바이러스, 썬데이(Sunday), 스콜피온(Scorpion), 크로우(Crow), FCL, CIH 바이러스가 있다.


2. 2세대 : 암호형 바이러스

- 바이러스 코드를 쉽게 파악하고 제거할 수 없도록 암호화한 바이러스

- 암호형 바이러스의 종류로는 슬로우(Slow), 캐스케이드(Cascade), 원더러(Wanderer), 버글러(burglar) 바이러스가 있다.


3. 3세대 : 은폐형 바이러스

- 바이러스에 감염된 파일들이 일정한 잠복 기간을 가지게 한 바이러스

- 은폐형 바이러스에는 브레인(Brain), 조시(Joshi), 512, 4096 바이러스가 있다.


4. 4세대 : 다형성 바이러스

- 코드 조합을 다양하게 할 수 있는 조합(Mutation) 프로그램을 암호형 바이러스에 덧붙여 감염된다. 실행될 때마다 바이러스 코드 자체를 변경시켜 식별자를 통해 구분하기 어렵게 한다.


5. 5세대 : 매크로 바이러스

- 응용 프로그램 및 사무용 관련 프로그램이 개발되면서 스크립트 형태의 실행 환경을 이용하여 전파되는 바이러스이다. 주로 MS 오피스 프로그램의 매크로 기능을 이용하여 감염된다.



Section 03 웜

- 인터넷 또는 네트워크를 통해서 컴퓨터에서 컴퓨터로 전파되는 프로그램이다.

- 다른 컴퓨터의 취약점을 이용하여 스스로 전파되거나 메일로 전파된다.


1. MASS Mailer 형 웜

- 자기 자신을 포함하는 대량 메일 발송을 통해 확산되는 웜이다.

- 제목이 없거나 특정 제목으로 전송되는 메일을 읽었을 때 감염되며, 시스템 내부에서 메일 주소를 수집하여 메일을 계속 발송한다.

- 주요 증상

◆ 감염된 시스템이 많으면 SMTP(TCP 25)의 네트워크 트래픽이 증가

◆ 베이글은 웜 파일을 실행할 때 'Can't find a viewer associated with the file' 같은 가짜 오류 메시지를 출력

◆ 넷스카이는 윈도우 디렉터리 밑에 CSRSS.exe을 만든다.

- 베이글(Bagle), 넷스카이(Netsky), 두마루(Dumaru), 소빅(Sobig) 등이 있다.

- MASS Mailer 형 웜은 내부 교육을 통해 예방가능


2. 시스템 공격형 웜

- 운영체제 고유의 취약점을 통해 내부 정보를 파괴 혹은 컴퓨터를 사용할 수 없는 상태로 만들거나 외부 공격자가 시스템 내부에 접속할 수 있도록 백도어를 설치한다.

- 주요 증상

◆ 과다한 TCP 135, 445 트래픽이 증가

◆ windows, windows/system32, winnt, winnt/system32 폴더에 SVCHOST.EXE 등의 파일을 설치

◆ 공격 성공 후 UDP 5599 등의 특정 포트를 열어 외부 시스템과 통신한다.

- 아고봇(Agobot), 블래스터(Blaster worm), 웰치아(Welchia) 등이 있다.


3. 네트워크 공격형 웜

- 특정 네트워크나 시스템에 대해 서비스 거부(DoS) 공격을 수행한다.

- 주요 증상

◆ 네트워크가 마비되거나, 급속도로 느려진다.

◆ 네트워크 장비가 비정상적으로 동작한다.

- 져봇(Zerbot), 클레즈(Klea) 등이 있다.



Section 04 기타 악성코드

1. 백도어와 트로이 목마

- 정상적인 인증 과정을 거치지 않고 운영체제나 프로그램 등에 접근할 수 있도록 만든 일종의 관리 목적의 통로이다.


2. 인터넷 악성코드

- 인가되지 않은 성인 사이트나 크랙 사이트 등에 접속할 때 감염된다.

- 예전에는 인터넷 악성코드로 끝나는 경우가 많았으나 최근에는 웜의 형태로 전이되고 있다.

- 주요 증상

◆ 인터넷 익스플로러의 시작 페이지가 계속 다른 곳으로 변경

◆ 인터넷 속도가 느려지거나 끊긴다.

◆ 시스템의 비정상적인 작동으로 운영체제가 사용 불능의 상태가 된다.


3. 스파이웨이

- 자신이 설치된 시스템의 정보를 원격지의 특정한 서버에 주기적으로 보내는 프로그램이다.

- 사용자가 주로 방문하는 사이트, 검색어 등 취향을 파악하기 위한 것도 있지만 패스워드 등과 같은 특정 정보를 원격지에 보내는 스파이웨어도 존재



Section 05 악성코드 탐지 및 대응책

- 악성코드 탐지에 사용되는 툴은 다음과 같다.

■ 윈도우 7 악성코드 : Win-Trojan.Pearmor

■ Process Explorer

■ Total Commander(http://www.ghisler.com)

■ CPorts(http://www.nirsoft.net/utils/cports.html)


1. 네트워크 상태 점검하기

- 상당수의 백도어는 외부(해커, 악성코드 작성자)와의 통신을 위해 서비스 포트를 생성한다.

- 주요 백도어의 사용 포트

포트번호 

트로이 목마 

포트번호 

트로이 목마 

21

 TrojanFore

1080 

WinHole 

23 

Tiny Telnet Server[TTS]

1090 

Xtreme 

25 

NaebiHappy

1150 

Orion 

31 

Agent, ParadiseMasters

1234 

Ultors Trojan 

41 

DeepThroat Foreplay 

1243 

Backdoor G 

80 

WWW Tunnel 

1245 

VooDoo Doll 

119 

Happy 99 

1257 

Frenzy 2000 

133 

Farnaz 

1272 

The Matrix 

137 

ChodeMSint(UDP) 

1441 

Remote Storm 

514 

RPCBackdoor 

1524 

Trin00 

555 

Seven Eleven 

1999 

Sub Seven 

666 

ServeU 

2140 

Deep Throat 1.3 

667 

SniperNet 

2255 

Nirvana

777 

AIM Spy

2583 

WinCrash

808 

WinHole

2773 

Sub Seven Gold 2.1 

999 

Deep Throat 

3459 

Eclipse 2000 

1001 

Silencer 

5400 

Blade Runner 

1016 

Doly Trojan 

5880 

Y3K Rat 

1024 

NetSpy 

8787 

BackOrifice  

- 시스템에서는 netstat 와 같은 명령으로 열려 있는 포트를 확인할 수 있다.


2. 정상적인 프로세스와 비교하기

- 대부분의 백도어는 티가 나지 않기 때문에, 윈도우와 유닉스 시스템 등의 정상적인 프로세스를 외워두면 비정상적인 프로세스를 식별하는데 많은 도움이 된다.

- 현재 동작 중인 정상적인 프로세스를 아는 것도 매우 중요. 윈도우의 작업 관리자에서 확인 가능하다.

- 다음의 20여 개의 프로세스는 윈도우 시스템이 동작힉 위한 기본 프로세스로 알아두면 유용하다.

● Csrss.EXE(Client/Server Runtime SubSystem : Win 32)

 - 윈도우 콘솔을 관장하고, 스레드를 생성/삭제하며 32비트 가장 MS-DOS 모드를 지원한다.

● Explorer.exe

 - 작업표시줄, 바탕화면과 같은 사용자 셸을 지원한다.

● Lsass.exe(Local Security Authentication Server)

 - Winlogon 서비스에 필요한 인증 프로세스를 담당한다.

● Mstask.exe(Window Task Scheduler)

 - 시스템에 대한 백업이나 업데이트 등에 관련된 작업의 스케줄러이다.

● Smss.exe(Session Manager SubSystem)

 - 사용자 세션을 시작하는 기능을 담당한다.

 - Winlogon, Win32(Csrss.exe)을 구동시키고, 시스템 변수를 설정한다.

 - 또한 Smss는 Wonlogon이나 Csrss가 끝나기를 기다려 정상적인 Winlogon, Csrss 종료시 시스템을 종료시킨다.

● Spoolsv.exe(Printer Spooler Service)

 - 프린터와 팩스의 스풀링 기능을 담당한다.

● Svchost.exe(Service Host Process)

 - DLL(Dynamic Link Libraries)에 의해 실행되는 프로세스의 기본 프로세스이다.

 - 한 시스템에서 여러 개의 svchost 프로세스를 볼 수 있다.

- 이 중에 웜/바이러스가 주로 사용하는 서비스명은 Csrss와 Svchost이다.

● Services.exe(Service Control Manager)

 - 시스템 서비스를 시작/정지시키고, 그들간의 상호 작용하는 기능을 수행한다.

● System

 - 대부분의 커널 모드 스레드의 시작점이 되는 프로세스이다.

● System Idle Process

 - 각 CPU마다 하나씩 실행되는 스레드로서 CPU의 잔여 프로세스 처리량을 %로 나타낸 값이다.

● Taskmgr.exe(Task Manager)

 - 작업관리자 자신

● Winlogon.exe(Windows Logon Process)

 - 사용자 로그인/로그오프를 담당하는 프로세스이다.

 - 윈도우의 시작/종료 시에 활성화되며 Ctrl+Alt+Delete 키를 눌렀을 경우에도 활성화된다.

● Winmgmt.exe(Window Management Service)

 - 장치에 대한 관리 및 계정 관리, 네트워크 등의 동작에 관련한 스크립트를 위한 프로세스이다.

● msdtc.exe(Distriduted Transaction Coordinator)

 - 웹 서버 및 SQL 서버 구동 시에 다른 서버와의 연동을 위한 프로세스이다.

● ctfmon.exe(Alternative User Input Services)

 - 키보드, 음성, 손으로 적은 글 등 여러가지 텍스트 입력에 대한 처리를 할 수 있도록 지원하는 프로세스이다.

● dfssvc.exe(Distributed File System (DFS))

 - 분산 파일 시스템에 대한 지원을 위해 백그라운드로 실행되고 있는 프로세스이다.


3. 백도어의 실질적인 파일 확인하기

- 네트워크 상태와 프로세스 분석을 통해 확인한 백도의 실질적인 파일을 확인한다.

- 악성코드 파일을 확인할 때는 total commander 같은 툴을 사용한다.

- 윈도우 탐색기가 악성코드에 이미 공격을 받았을 때는 특정한 파일이 숨겨져서 보이지 않거나 삭제되지 않는 경우도 있다.

- 파일 확인 과정에서 반드시 확인하고 가야할 폴더인 C:\Windows\system32 가 있다. 이 폴더에는 주요 DLL과 운영체제의 기본적인 실행 파일이 존재하는데, 대부분의 악성코드는 이 폴더를 공략한다.

- 폴더 내에서 가장 최근에 생성된 파일 중에 이상한 것이 없는지 확인하는 방법을 우선 이용한다.


4. 시작 프로그램과 레지스트리 확인하기

- 시작 프로그램 목록은 'msconfig' 명령을 통해 쉽게 확인할 수 있다.


5. 백도어 제거하기

- 확인한 백도어를 삭제하는 절차는 다음과 같이 할 수 있다.

① 백도어 프로세스의 중지

② 백도어 파일의 삭제

③ 레지스트리 삭제

 - regedit 으로 레지스트리 경로를 확인할 수 있다.





출처 : 정보 보안 개론(한 권으로 배우는 보안 이론의 모든 것) / 양대일 저 / 한빛아카데미 출판

':: 리버싱' 카테고리의 다른 글

UPack PE 헤더 분석 + 디버깅  (1) 2016.12.31
Red_Seek :: 스택 프레임  (0) 2014.01.29
[Red_Seek] abex' crackme #1 (크랙미 #1)  (0) 2014.01.23
[Red_Seek] 스택  (0) 2014.01.22
[Red_Seek] IA-32 Register  (0) 2014.01.14
posted by Red_Seek
2016. 11. 6. 23:24 :: 문제풀이/WebHacking,kr

안녕하세요. Message입니다.

Webhacking.kr Lv8 문제풀이입니다. 

 

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

1. 문제분석

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

 

문제 메인에 접속하면 아래와 같은 문구가 뜹니다.

새로고침을 누르니 카운트가 늘어납니다.

최대치인 70번까지가 시도할 수 있는 횟수인걸까요?

 

 

소스코드를 살펴보니 "<!-- index.phps -->" 힌트가 있습니다.

 

해당 페이지에 접속하면 아래와 같은 소스코드가 나타납니다.

 

 

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

2. 문제풀이

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

 

1) 문제 의도파악

소스코드를 살펴보면 아래부분에

"select id from lv0 where agent='$_SERVEr[HTTP_USER_AGENT]'" 쿼리문의 결과로

"admin" 값이 얻어지면 $solve() 함수가 호출됨을 알 수 있습니다.

 

 

2) 장애물

우리가 원하는 "admin" 값이 나오려면 여러가지 방법이 있습니다.

가장 빨리 생각난건 지난 문제의 해결방법이었던 union을 이용하는 방법입니다.

하지만 이번 문제에서는 preg_match() 함수를 이용하여

"union"을 비롯한 "char, ascii" 등의 문자는 물론, 여러가지 특수문자를 모두 필터링하고 있습니다.

 

3) 이용할것

처음에는 DB를 검색하는 Select 문을 조작해서 어딘가에 있을 "admin" 값을 찾아와야 하나? 싶었습니다.

하지만 그런 방법은 맨땅에 헤딩하는 느낌이 들더군요. "admin"값이 없을수도 있죠.

결국 직접 "admin" 값을 입력해야 한다는 생각이 들었고 union, char 등을 이용한 공격을 시도해보았지만,

시도하면 할수록 필터링이 잘되있다는 깨달음만 얻었지요.

이런 방법이 아닌가 싶다가 PHP 소스 아랫부분을 살펴보니, INSERT문이 보입니다.

위의 쿼리문에 대한 결과가 "admin"이 아닐경우, guest의 접속 여부를 기록하기 위한 쿼리로 보입니다.

 

$ip 변수를 조작하기 보다는, 버프를 이용하여 $agent 값을 변경해야겠다는 생각이 듭니다.

또한 결정적으로 따옴표가 치환되는 부분은 $agent 변수가 아니라 $_SERVER[HTTP_USER_AGENT] 기 때문에

$agent를 변경해도 문제를 클리어할 수 있습니다.

 

4) 공격시도

지난 문제에서 연습한대로 APMSETUP에서 테스트를 수행합니다.

수행하기에 앞서 아래와 같은 절차대로 간단히 필드2개 짜리 테이블을 생성하고 쿼리문을 날려봅니다.

 ① DB

      - DB선택 :  use db이름;

     - 테이블생성 :  create table test(name varchar(20) NOT NULL, passwd varchar(20) NOT NULL);

     - 래코드삽입 :  insert into table이름(필드명1, 필드명2) values(data1, data2); 

 ② PHP

     - DB연결 :  $conn = mysql_connect('localhost', 'root', 'apmsetup');

     - DB선택 :  $db_id = mysql_select_db("mysql", $conn);

     - 질의 :  $query = @mysql_query("insert into test2(name, passwd) values('message', 'admin')";#','guest')");

     - 실행 :  mysql_query($q, $conn);

 

처음에는 PHP 소스코드 형식에 맞추기 위해 다음과 같이 쿼리문을 날렸습니다 message', 'admin')";#

나름대로 아래의 PHP소스상에서 주석처리와 쌍따옴표까지 고려를 한것이죠.

 

하지만 아래와 같이 쿼리문 에러와 함께 DB에서도 오류가 나더군요. 형식이 맞지 않습니다.

쌍따옴표는 PHP소스코드 상에서 문자열을 표시하기 위해 사용된 부분이군요.

이래서 직접 DB에 테스트 하지 않으면, 어떤 오류가 나는지도 모르고 헤메는 경우가 많은듯 합니다.

 

따라서 다음과 같이 수정하여 쿼리문을 날립니다(쌍따옴표 제거) → message', 'admin');#

APM 환경에서는 성공적으로 질의문이 수행됩니다.

 

실제 문제풀이 사이트에 접속합니다.

버프슈트를 이용하여 User-Agent에 테스트 완료된 문자열을 입력해줍니다.

인자수를 맞추어 줘야 하기 때문에, 의미없는 루프백 주소를 추가해서 총 3개의 인자를 넣어줍니다.

message','127.0.0.1','admin');#

이후에 User-Agent를 message 로 조정해서 쿼리를 날리면

"admin" 값을 가져오면서 성공입니다!

 

 

By Red_Message.

posted by Red_Message
2016. 11. 4. 23:50 :: 문제풀이/WebHacking,kr

안녕하세요. Message입니다.

Webhacking.kr Lv7 문제풀이 달립니다!

! 빠른 문제풀이 보다는 풀이과정 속에서 이것 저것 배우는것을 목표로 합니다.

 

 

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

1. 문제분석

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

 

7번 문제에 접속합니다.

auth 버튼을 누르면 "Access_Denied!" 창이 뜹니다.

 

개발자도구로 소스코드를 살펴보면,

"<!-- admin mode : val=2 -->" 이라는 주석과 "index.phps" 주석을 볼 수 있습니다.

 

해당 주석에 적힌 내용을 바탕으로 val=2 페이지와 index.phps 페이지에 접속하면 아래와 같습니다.

 

 

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

2. 문제풀이

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

 

소스코드를 쭉 살펴보면

 

우리의 최종 목표는 소스코드의 맨 아래에 있는 "$data[0]==2" 조건을 가진 IF문을 충족시켜서

숨겨진 button을 얻어야 한다는 것을 알 수 있습니다.

 

변수 $data에 값을 할당하려면 DB에서 값을 얻어오는 mysql_fetch_array 함수에

인자로 들어가는 변수 $result에 어떤 값이 들어가는지 살펴봐야 합니다.

변수 $result에 들어가는 값은 아래 소스코드에서 알 수 있듯이

웹페이지 방문자가 입력하는 $go 변수에 어떤 값이 들어가느냐에 따라 달라집니다.

 

또한 특수문자 * / 를 사용할 수 없으며, "--" "2150" "\+" 등의 문자를 사용할 수 없는 제약과

rand() 함수로 인해서, 우리가 제대로 입력을 해도 4/5 확률로 die() 함수가 실행될 수 있습니다.

 

주어진 힌트는 아래와 같이 val=2는 존재하지 않는다와 union을 이용하라는 내용입니다.

 

1) 1차시도

일반적인 union select 공격 쿼리를 날려보았습니다.

"select lv from lv1 where lv=( 1) union select lv ...(생략).. )"

하지만 공백 "%20" 테이블명 "lv" 등에서 필터링되어 접근거부되었습니다.

 

2) 2차시도

가장 시급한것은 스페이스 구문을 사용하지 않고 UNION 쿼리를 날리는것입니다.

구글링을 해보니 스페이스를 사용하지 않는 UNION 구문 예시가 있더군요 ex)  union(select("필드")from("테이블명") 

그래서 2번 문제와 동일하게 MYSQL에서 미리 테스트를 해보고 시도 해보기로 했습니다.

 

일단 평범한 SELECT 문에 UNION 쿼리를 날려 차이점을 살펴보았습니다.

기존에 검색되던 내용에서 추가로 2개의 쿼리가 검색되더군요.

 

그리고 제가 원했던 스페이스가 아닌 괄호로 표현된 UNION 쿼리문을 날려보았습니다.

동일한 결과가 나오는것을 확인합니다.

 select user from user user union(select(password)from(user));

 

그리고 이어지는 테스트는 우리가 푸는 문제에서 주어진대로 WHERE 조건이 추가된 부분에서

공백없이 UNION 쿼리를 입력하였을 경우입니다.

 select user from user where user=('root')union(select(password)from(user));

 

하지만 UNION SELECT의 결과는 앞에 있는 SELECT문의 뒤에 이어진다는 단점이 있습니다.

우리가 원하는건 data[0]에 값2가 들어가는것입니다.

따라서 앞에있는 SELECT의 WHERE에 적절한 값을 넣어주면 검색되는 쿼리가 없을것이고

우리가 넣은 UNION SELECT의 값만 나올것입니다.

 

이제 다음 목표는 결과값에 우리가 얻어야할 숫자 2가 나오는것입니다.

여기저기 구글링을 해보니 UNION SELECT에서 필드명에 숫자를 넣는 예제가 보여서

테스트도 할겸 필드명에 숫자를 넣어보았더니, 아래처럼 제가 넣어준 숫자가 나오더군요.

그리고 임의로 여러가지의 숫자를 넣어봤더니, 넣어준 숫자가 그대로 나옴을 알 수 있었습니다.

 

마지막으로 해결해야할 문제는 테이블명입니다. 우리가 넣어야 하는 테이블명 "lv"는 필터링되는

문자이므로, 동일하게 숫자를 넣어 우회해보려 했지만 오류가 나더군요.

그래서 혹시나? 하고 FROM을 아예 지워서 테스트해보았습니다.

OLLEH! 쿼리가 검색이 되네요

 

해당 내용을 바탕으로 아래와 같이 URL을 작성하여 날려보았습니다.

하지만 여지없는 "Access Denied!"

http://webha...(중략)...web-07/index.php?val=999)union(select(2))

 

이유는 숫자 또한 필터링 되어 있기 때문입니다.

2라는 숫자를 못쓰기 대문에 "1+1", "4/2" 등을 시도해보았지만 역시 실패입니다.

하지만 "-" 가 필터링 되어 있지 않은 부분을 발견하여 아래와 같이 마이너스로 넣어보았습니다.

http://webha...(중략)...web-07/index.php?val=999)union(select(3-1)

 

"nice try" 는 rand 함수에 의해 5/4 확률로 발생하는 문구입니다.

일단 필터링 단계는 지나쳤다는 의미죠.

내부 소스코드에서 아래와 같이 적용될때(rand 결과가 1)까지 F5를 눌러줍니다.

계속 URL 쿼리를 날리면 1/5 확률로 원하는 값을 얻어낼 수 있습니다.

 select lv from lv1 where lv=(999)union(select(2))

 

By Red_Message.

 

posted by Red_Message
2016. 11. 3. 04:15 :: 웹 보안

Chapter 04 웹 보안

Section 01 웹에 대한 이해

- 웹은 처음에는 단순히 대학 내 각 연구실 사이의 데이터 전송을 위해, 하나의 시스템과 다른 하나의 시스템 간의 통신을 위한 프로토콜을 만들어 사용했다.

- 그러다 점차 프로토콜이 하나둘씩 늘어 결국 시스템을 만드는 회사마다 서로 다른 통신 프로토콜을 사용하게 된 것이다.

- 개별 시스템 산의 통신에는 큰 문제가 없었으나 다른 회사의 제품들과 서로 통실할 수 없다는 문제점이 발생

- 이를 해결하기 위해 하나의 프로토콜을 해석한 후 다른 프로토콜로 바꾸어 다른 시스템으로 전송해주는 장치인 게이트웨이(Gateway)를 개발했다.

- 게이트웨이가 나온 후에야 원격의 두 지점 간의 통신이 가능해졌고, 비로소 네트워크라고 부를 만한 것이 생겼다.


- 1969년 미 국방부 산하 고등연구 계획국 ARPA(Advanced Research Projects Agency)에 의해 전 세계 주요 거점을 연결하는 네트워크가 처음 만들어졌다.

- 이 네트워크를 알파넷이라 부르며, 흔히 알파넷을 인터넷의 시작이라고 한다.


- 1970년대의 네트워크는 TCP/IP 프토로콜로 연결되고 일반에 공개됨에 따라 크게 발전하기 시작

- 우리나라의 경우 1994년 한국통신이 카이스트와 연구기관 등에 학술 교융/정보 교류용으로 제공한 '하나망'을 일반에 공개하고 코넷(KORNET)을 시작함으로써 인터넷에 첫 발은 내딛게 되었다.


- '웹'의 정식 명칭은 월드 와이드 웹(WWW : World Wide Web)이다.

- 세계 규모의 거미집 또는 거미집 모양의 망이라는 뜻으로, 1989년 스위스 제네바에 있는 유럽 원자핵 공동 연구도(CERN)에서 근무하던 팀 버너스 리(Tim Berners Lee)에 의해 연구 목적의 프로젝트로 시작

- 프로젝트의 목적은 전 세계에 흩어져 있는 종업원 및 연구자와 연구 결과나 아이디어를 공유할 수 있는 방법을 모색하는 것이었다.

- 처음 프로젝트를 계획할 당시에는 웹을 'Hyper Text Project'라고 불렀는데, 이는 1960년대에 테드 넬슨이 만든 신조어로 다른 문서와 연관 관계를 가지는 텍스트를 의미하는 것이다.

- 현재 웹 문서로 가장 흔히 쓰이는 HTML(Hyper Text Markup Language)은 이 Hyper Text를 효과적으로 전달하기 위한 스크립트 언어이다.

- 웹에 접근하기 위해서는 웹 브라우저가 필요하다. 최근에는 대부분 마이크로소프트의 인터넷 익스플로어를 사용하지만, NCSA에서 개발한 모자이크(Mosaic)나 넷스케이프에서 개발한 넷스케이프 네비게이터(Netscape Navigator) 등도 있다.



Section 02 HTTP에 대한 이해

- 웹에서는 FTP, Telnet, HTTP,  SMTP, POP 등 여러 프로토콜이 쓰인다. 그중 가장 흔히 사용되는 프로토콜이 HTTP이다.

- HTTP를 이용하면 사용자는 다양한 응용 프로그램에 접근하여 텍스트/그래픽/애니메이션을 보거나 사운드를 재생할 수 있다.

- HTTP는 웹 처리 전반에 걸쳐 토대가 되기 때문에 웹 서버를 HTTP서버라고 부르기도 한다.

- 웹 서버에는 웹 서비스를 구현하기 위한 웹 언어가 존재하며, 그 종류는 HTML, ASP, JSP, Java Script 등이 있다.


1. HTTP 프로토콜

- HTTP는 0.9 버전부터 사용되었다.

- 0.9 버전은 서버로부터의 단순 읽기 기능만 지원한다.

- HTTP 0.9는 하나의 웹 페이지 안에서도 텍스트와 그림마다 Connect 과정을 반복해서 거쳐야 했기 때문에 무척 비효율적이었고 오래 사용되지 못했다.

- 하지만 1.0 버전부터는 한 번의 Connect 후에 Request와 Response를 반복할 수 있게 되었다.


2. HTTP Request

- HTTP Reauest는 웹 서버에 데이터를 요청하거나 전송할 때 보내는 패킷으로, 주로 GET, POST와 같은 메소드를 사용한다.


가. GET 방식

- 가장 일반적인 HTTP Reauest 형태로 웹 브라우저에 다음과 같은 요청 데이터에 대한 인수를 URL(Uniform Resource Locator)을 통해 전송한다.

www.wishfree.or.kr/list.php?page=1&search=test

- GET 방식에서는 각 이름과 값을 &로 결합하며 글자 수를 255자로 제한한다.

- 데이터가 주소 입력란에 표시되기 때문에, 최소한의 보안도 유지되지 않는, 보안에 매우 취약한 방식이다.

- 간혹 아이디나 패스워드가 인수로 저장되러 전달되는 경우도 발생한다.


나. POST 방식

- URL에 요청 데이터를 기록하지 않고 HTTP 헤더에 데이터를 전송하기 때문에 GET 방식에서의 '?page=1&search=test' 와 같은 부분이 존재하지 않는다.

- 내부의 구분자가 각 파라미터(이름과 값)를 구분하며, 서버가 각 구분자에 대한 내용을 해석하여 데이터를 처리하기 때문에 GET 방식에 비해 상대적으로 처리 속도가 늦다.

- 인수 값을 URL을 통해 전송하지 않기 때문에 다른 이가 링크를 통해 해당 페이지를 볼 수 없다.

- 게시판 등에서 파일 업로드는 POST 방식으로만 할 수 있는데, GET 방식과는 달리 보내려는 데이터가 URL을 통해서 노출되지 않기 때문에 최소한의 보안성은 갖추고 있다.


다. 기타 방식

① HEAD 방식 : 서버 측의 데이터를 검색하고 요청하는데 사용한다.

② OPTIONS 방식 : 자원에 따라 요구/응답 관계에서 관련된 선택 사항의 정보를 요청할 때 사용된다. 이를 통해 클라이언트는 어느 것을 선택할지 결정할 수 있고, 자원과 관련 필요 사항도 결정할 수 있다. 서버의 수행 능력도 알아볼 수 있다.

③ PUT 방식 : 메시지에 포함되어 있는 데이터를 지정한 URI(Uniform Resource Identifier) 장소에 그 이름으로 저정한다.

④ DELETE 방식 : URI에 지정되어 있는 자원을 서버에서 지울 수 있게 한다.

⑤ TRACE 방식 : 요구 메시지의 최종 수신처까지의 루프백 검사용으로 쓰인다. 클라이언트가 보내는 요구 메시지가 거쳐가는 프록시나 게이트웨이의 중간 경로 및 최종 수신 서버까지 이르는 경로를 알아내는데 사용된다.


3. HTTP Response

- 클라이언트의 HTTP Request에 대한 응답 패킷이다.

- 서버에서 쓰이고 있는 프로토콜 버전, Request에 대한 실행 결과 코드 및 간략한 실행 결과 설명문(OK 등)의 내용이 담겨있다.

- 전달할 데이터의 형식과 데이터 길이 등과 같은 추가 정보가 MIME 형식으로 표현되어 있는데, 헤더 정보 귀에는 실제 데이터(HTML이나 그림)가 전달되며 데이터 전달이 끝나면 서버는 연결을 끊는다.

- HTTP Response의 주요 실행 결과 코드

실행 결과 코드 

내용

설명

100번대 

정보 전송 

HTTP/1.0까지는 계열에 대한 어떤 정의도 이루어지지 않았기 때문에 실험적인 용도 이외에는 100대 서버 응답은 없다. 

200번대 

성공 

클라이언트의 요구가 성공적으로 수신되어 처리되었음을 의미 

300번대 

리다이렉션 

해당 요구 사항을 처리하기 위해 사용자 에이전트에 의해 수행되어야 할 추가적인 동작이 있음을 의미 

400번대 

클라이언트 측 에러 

클라이언트에 오류가 발생한 경우 사용된다.  

500번대 

서버 측 에러 

서버 자체에서 발생된 오류 상황이나 요구 사함을 제대로 처리할 수 없을때 사용된다. 



Section 03 웹 서비스에 대한 이해

- 웹 서비스는 웹 언어를 통해 제공된다.

- 정적인 서비스 제공 언어 : HTML, 자바 스크립트, 비주얼 베이직 스크립트 등

- 동적인 서비스 제공 언어 : ASP, JSP, PHP 등


1. HTML

- HTML(Hyper Text Markup Language)은 가장 단순한 형태의 웹 언어이다.

- 웹 서버에 HTML 문서를 저장하고 있다가 클라이언트가 특정 HTML페이지를 요청하면 해당 HTML 문서를 클라이언트로 전송한다.

- 그러면 클라이언트는 이 웹 페이지를 해석하여 웹 브라우저에 표현해 주는데 이런 웹 페이지를 정적인(Static) 웹 페이지라고 한다.

- 정적인 웹 페이지는 고객의 취향이나 변화에 적응할 수 없고 새로운 것을 추가하는데 많은 시간이 걸린다는 단점이 있지만 보안에는 장점이 많다.

- 웹 해킹은 웹 브라우저와 웹 서버 사이에 전달되는 값들의 변조를 통해 웹 서버의 설정이나 로직을 바꾸는데, 정적인 웹 페이지는 '바쑬수 있는 가능성'이 매우 낮다.


2. SSS

- 사용자들은 점차적으로 웹 페이지가 각기 다른 요구에 따라 능동적으로 변하기를 기대했다.

- 동적인(Dynamic) 웹 페이지를 제공할 수 있는 PHP(Personal Home Page), ASP(Active Server Page), JSP)Java Script Pages)와 같은 언어를 개발했다.

- 동적인 페이지를 제공하는 스크립트를 SSS(Server Side Script)라 한다.

- 동적인 웹 페이지에서는 스크립트에 HTML 확장자 대신 ASP 또는 JSP 의 확장자를 가진 웹 문서를 요청한다.

- ASP의 경우 DLL이나 OCX 같은 파일을 이용하고 JSP의 경우 서블릿을 이용해 요청을 처리한다.

- 그리고 결과를 HTML 파일로 만들어 클라이언트에 전송해준다.

- ASP를 이용하기 위해서는 윈도우 기반의 IIS 웹 서버를 설치해야 하지만 JSP는 어떤 운영체제에서도 동작한다.


3. CSS

- 서버가 아닌 클라이언트 측의 웹 브라우저에 의해 해석되고 적용되는 스크립트이다.

- 자바 스크립트, 비주얼 베이직 스크립트 등

- 이를 CSS(Client Side Script)라 한다.

- CSS는 서버가 아닌 브라우저에서 해석되어 화면에 적용되기 때문에 웹 서버의 부담을 줄여주면서도 다양한 기능을 수행할 수 있다.



Section 04 웹 해킹에 대한 이해

- 웹 해킹은 웹 사이트의 구조와 동작 원리를 이해하는 것에서부터 시작한다.


1. 웹 취약점 스캐너를 통한 정보 수집

- 웹에 대한 정보를 수집할 때는 웹의 메뉴를 하나하나 클릭해보며 수작업으로 동작을 파악하기도 하지만 웹 취약점 스캐너를 사용할 수도 있다.

- 스캐너를 통하면 웹 구조를 파악하고 취약점을 수집하기가 쉽지 않다는 단점이 있다. 각 페이지의 링크 정보를 따라가는 것이므로 웹 페이지에서 링크로 제공하지 않는 페이지는 구조 분석이 어렵다.

- 한편 각 페이지에서 링크 정보를 따라가며 웹 사이트의 웹 페이지를 로컬에 저장해주는 Web Zip이 있는데, 웹 스캔은 Web Zip이 웹 페이지를 수집하는 원리와 같다.

- 웹 프로그램은 자유스럽게 만들어지고 변형도 다양해 웹 스캐너가 취약점을 정확히 잡아내기랑 거의 불가능하다.

- 따라서 스캐너를 통해 발견된 취약점은 개별 확인 과정을 통해 유효성을 확인하는 과정이 필요하다.


2. 웹 프록시를 통한 취약점 분석

- 웹 프록시의 기본적인 동작 구조는 클라이언트에 설치되며 클라이언트의 통제를 받는다. 즉 클라이언트가 웹 서버와 웹 브라우저 간에 전달되는 모든 HTTP 패킷을 웹 프록시를 통해서 확인하면서 수정하는 것이 가능하다.


가. 서버에서 클라이언트로 전송되는 패킷 변조

- 웹 프록시의 유용한 점은 서버와 클라이언트 사이의 패킷을 볼 수 있는 것 이외에 서버와 클라이언트 사이에 전달되는 과정에서 패킷을 위변조할 수 있다는 점이다.

- 변조하고자 하는 패킷은 ASP 혹은 JSP가 아닌 HTML이다. 어떤 언어로 개발됐는지 웹 프록시를 통해서 확인하는 것은 HTML이다.

- 서버에서 클라이언트로 전송되는 내용이 바꾸었으니 자신을 해킹한 것이된다. 하지만 이런 공격이 다음 두가지 위력을 가질 수 있다.

- 첫 번째. 클라이언트에 해킹하고자 하는 대상이 있는 경우

웹 브라우저 내용만 바꾸었지만 실제로는 Active X 등의 형태로 여러 프로그램이 클라이언트에 설치되어 웹 서비스를 제공하는 경우가 많은데, 이때 클라이언트에 설치된 서비스 프로그램을 속이는 것이 가능하다.

- 두 번째. 서버에서 클라이언트에 정보를 전송했다가 이를 다시 전송받아 처리하는 경우

예를 들면 경품을 나눠주기 위한 당첨권은 동전으로 긁으면 '당첨'이란 글자가 나타나므로 가게 주인은 '당첨'이란 글씨를 보고 당첨 여부를 판단할 것이다. 그런데 어떤 사람이 '당첨'이란 글씨를 자신이 받은 당첨권에 위조해서 적으면(이 과정은 마치 서버가 클라이언트에게 전달해준 패킷 값을 위변조하는 것과 같다.) 제대로 위조를 했다면 가게 주인(서버)은 경품을 꺼내줄 것이다.

이처럼 서버가 클라이언트로 보낸 데이터의 변조로 인해 발생하는 위험을 없애려면 서버에서 클라이언트로 전송한 값은 어떤 것도 다시 참조하지 않아야 한다.


나. 클라이언트에서 서버로 전송되는 패킷 변조

- 서버에서 클라이언트로 전송되는 패킷을 변조한 것과 클라이언트에서 서버로 전송되는 패킷을 변조하는 것은 같다.

- 클라이언트에서 서버로 전송되는 패킷을 변조하는 것은, 일반적인 웹 서비스의 메뉴상 접속할 수 없는 것에 접근하거나 특정한 값을 넣어 시스템의 오작동을 유도하기 위한 목적으로 사용된다.


3. 구글 해킹을 통한 정보 수집

- 구글에서 제공하는 고급 검색 기능

검색 인자 

설명

검색 추가 인자

site 

특정 도메인으로 지정한 사이트에서 검색하려는 문자열이 포함된 사이트를 찾음 

YES 

filetype 

특정한 파일 유형에 한해서 검색하는 문자가 들어 있는 사이트를 찾음 

YES 

link 

링크로 검색하는 문자가 들어 있는 사이트를 찾음 

NO 

cache 

특정 검색어에 해당하는 캐시된 페이지를 보여줌 

NO 

intitle 

페이지의 제목에 검색하는 문자가 들어있는 사이트를 찾음 

NO 

inurl 

페이지의 url에 검색하는 문자가 들어있는 사이트를 찾음

NO 

- 검색 엔진의 검색을 피하는 방법으로 가장 일반적인 대응법은 웹 서버의 홈 디렉토리에 robot.txt. 파일을 만들어 검색할 수 없게 만드는 방법



Section 05 웹의 주요 취약점 10가지

1. 명령 삽입 취약점

2. XSS 취약점

3. 취약한 인증 및 세션 관리

4. 직접 객체 참조

5. CSRF 취약점

6. 보안 설정 취약점

7. 취약한 정보 저장 방식

8. URL 접근 제한 실패

9. 인증 시 비암호화 채널 사용

10. 부적절한 오류 처리



Section 06 웹 취약점 보완

1. 특수문자 필터링

- 웹 해킹의 가장 기본적인 형태 중 하나가 인수 조작인데 인수 조작은 예외적인 실행을 유발시키기 위해 일반적으로 특수 문자를 포함하게 되어 있다.

- SQL 삽입 공격에서 아이디와 패스워드 넣는 부분에 ' 문자열을 입력받지 못하도록 코드를 수정하여 보완할 수 있다.

- XSS 공격에서 본문에 포함되는 주요 특수문자를 제거하는 함수 등을 사용하여 보완할 수 있다.


2. 서버 측 통제 작용

- 파일 업로드 취약점이나 특수문자 필터링을 수행할 때 주의할 점은 자바 스크립트와 같은 CSS(Client Side Script) 기반의 언어로 필터링을 하면 안된다.

- CSS 기반의 언어는 웹 프록시를 통해 브라우저에 전달되기 때문에 전달되는 과정에서 변조될 가능성이 있다.

- 즉 필터링 로직은 ASP, JSP 등과 같은 SSS(Server Side Sctipt)로 필터링을 수행해야 한다.


3. 지속적인 세션 관리

- URL 접근 제한 실패를 막기 위해서는 기본적으로 모든 웹 페이지에 세션에 대한 인증을 수행해야 한다.

- 모든 웹 페이지에 대해 일관성 있는 인증 로직을 적용하려면 기업 단위에서 또는 웹 사이트 단위에서 세션 인증 로직을 표준화하고, 모든 웹 페이지를 개발할 때 해당 표준을 준수시켜야 한다.




출처 : 정보 보안 개론(한 권으로 배우는 보안 이론의 모든 것) / 양대일 저 / 한빛아카데미 출판

posted by Red_Seek
2016. 10. 16. 17:46 :: 문제풀이/Pracical Malware

안녕하세요. Message입니다.

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

이번 실습은 동적분석과 정적분석 이후에 교재의 문제를 풀이합니다.

 

분석환경은 WindowXP / Vmwre 12.1.0 build 입니다.

  # Windows7 에서 분석 수행 시 오류가 발생하여 멈추는 현상이 발생할 수 있습니다.

  # 기본적으로 실습교재의 샘플들은 XP에 최적화 되어 있습니다.

 

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

1. 기초 동적 분석

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

문제풀이에 앞서 간단한 동적 분석을 진행합니다.

 

1. PE구조 & 패킹

exe 파일과 dll 파일 모두 별도의 패킹이 되어 있지 않습니다.

 

 

2. DLL

1) Lab07-03.EXE

기존에 실습했던 악성코드가 임포트하는 DLL과 다를바가 없습니다.

 

하지만 임포트 함수 중 CreateFileA, CreateFileMappingA, MapViewOfFile은 프로그램이

파일을 오픈해 메모리로 매핑함을 알려줍니다. 사실 해당 함수는 지난 실습에서 꾸준히 등장했지만

분석 포커스에 빗나가 있었기 때문에 주목(?) 받지 못했습니다.

또한 FindFirstFileA, FindNextFileA, CopyFileA 함수를 이용하여 디렉토리를 탐색하고

CopyFileA를 통해 악성코드 본인 또는 특정 파일을 복사할 것으로 짐작됩니다.

주목할만한 점은, Lab07-03.dll을 어떤 방식으로든 사용할 것이 분명하지만, 

지금까지 많이 보아 왔던 LoadLibrary, GetProcAddress 함수가 임포트 목록에 없는 사실은

런타임에 해당 DLL을 로드하지 않고 다른 방법을 사용하고 있음을 짐작케 합니다.

 

2) Lab07-03.DLL

Lab07-03.dll이 임포트하는 dll 파일은 WS2_32.dll 입니다.

교재의 첫 실습[1-1]을 통하여 공부했던 네트워크 관련 API들이 얼핏 기억납니다.

검색해보니 2014년도에 포스팅이네요.

 

특이한점은 dll의 주요 역할인 Export 목록이 비어있다는 점입니다.

익스포트가 없으면 다른 프로그램이 임포트할 수 없습니다.

이를 염두해두고 분석을 진행합니다.

 

3. String

1) Lab07-03.EXE

지난번 "kernel32.dll" 파일명을 "kerne132.dll" 으로 위장한 악성코드를 실습한 이후부터는

String 윈도우에서 관련 문자열을 발견하면 숫자가 섞이지 않았나 체크하게됩니다.

역시 영문자 L 을 숫자 1로 변경한 kerne132.dll 문자열이 보입니다.

 

2) Lab07-03.DLL

악성코드가 접속을 시도할것으로 추정되는 IP(127.26.152.13)가 눈에 띕니다.

.data 영역의 "exec, sleep, hello" 문자열을 통하여 네트워크 통신 관련된 기능을 염두해 둡니다.

 

4. Function Calls

이번 실습에서는 기존에 사용해본적 없는 [ Function Calls ] 윈도우를 사용해봅니다.

특히 현재 분석중인 DLL은 DllMain 중심으로 대부분의 기능을 구현하고 있기 때문에

호출하는 함수만 요약하여 볼 수 있는 기능이 악성코드 동적/정적 분석에 속도를 더해줍니다.

 

1) Lab07-03.EXE

CreateFileA, CreateFileMappingA, MapViewOfFile 등의 메모리맵 파일에 관련된 API들이 보입니다.

메모리맵 파일의 기능을 이용하면 EXE/DLL 파일의 읽기/쓰기를 할 수 있기 때문에

LoadLibrary, GetProcAddress 함수를 사용하지 않고도 DLL 파일을 사용할 수 있습니다.

메모리맵 파일을 사용하기 위해서는 3단계 실행흐름(CreateFIle > CreateFileMapping > MapViewOfFile)을 가지며,

아래의 Function Calls 에 나오는 함수명과 호출 순서가 일치합니다.

또한 중간에 서브루틴 sub_401040이 여러번 등장합니다. 아직 어떤 기능인지 알 수 없지만

빈번하게 호출되는 서브루틴임을 참고하고 넘어갑니다.

 

2) Lab07-03.DLL

지난 실습에서 마주쳤던 Mutex 관련 함수들(OpenMutex, CreateMutexA)이 보입니다.

해당 함수들을 이용하여 악성코드의 중복 실행을 방지하는것으로 추측됩니다.

또한 네트워크 연결을 위한 소켓 관련 함수들(socket, inet_addr, htons, connect, send, recv, closesocket)도 보입니다.

어떤 내용을 주고받는지는 모르겠지만, 대략적인 흐름이 보입니다.

 

 

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

2. 정적분석

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

문제를 풀이를 위한 정적분석을 진행합니다.

 

1. Lab07-03.DLL

1) 전체적인 코드구조 파악

DLL 파일의 DllMain을 Graph overview 윈도우로 살펴보면 매우 복잡해 보입니다.

똑같겠지 생각하고선 [Flow Chart/F12] 를 실행해보니 분기점이 정리된 그래프가 나오더군요.

그래프 오버뷰에서는 파악하지 힘들었지만, 조건문이 많다는걸 한눈에 알 수 있었습니다.

 

실제로 Hex-ray 기능을 이용해보면 다수의 If 문이 존재함을 알 수 있습니다.

아마 코드를 먼저 보았다면 머리속이 복잡했을테지만

함수목록으로 함수 목록을 체크한 것이 실행 흐름을 파악하는데 많은 도움이 되었습니다.

 

 

2) 스택할당

DllMain 초반 도입부에서 __alloca_probe 함수가 보입니다.

사실 이 함수는 책에서도 가볍게 언급하고 있을 뿐이며, 악성코드 분석에 있어서 중요한 부분은 아닙니다.

하지만 매번 보던 스택프레임이 아니어서 약간 찜찜하기도 했고

삽질 하다보니 배우는게 여럿 있어 살펴보았습니다. 악성코드의 핵심 내용만 보시려면 3)번 항목으로 직행하세요~

 

책에서는 "스택에 공간을 할당하는 함수이며, 프로그램이 큰 스택을 사용함을 알 수 있음" 이라고 설명합니다.

정확한 명세를 알아보고자 구글링을 했더니, 해당 함수에 대해 명확한 설명을 찾지 못했습니다.

 

이것저것 삽질을 하다가 Ollydbg를 통해 살펴보니

__alloca_probe 함수를 호출하는 명령 라인에 "Allocates 4600, bytes on stack" 코멘트가 달려 있었습니다.

코멘트의 4,600이라는 숫자는 __alloca_probe 함수 호출 바로 윗라인에서 EAX 레지스터에 넣어준 11F8 Hex값 입니다.

 

EAX 레지스터에 넣어준 값이 스택 할당에 영향을 주었다는 연관성은 알겠지만,

push를 통해서 인자를 전달한게 아니기 때문에 약간 의아했기에 함수 내부를 살펴보았습니다.

지금까지 함수 호출시에 넣어주는 인자들은 "push" 명령어를 사용한다는 고정관념을 깨고

함수의 정의 부분에서 EAX레지스터가 매개변수로 되어 있음을 발견하였습니다.

 Tip. __usercall vs __userpurge

 Hex-ray 기능을 사용하면 두가지 Calling Convention을 만날 수 있습니다.

 __usercall : 스택정리를 caller가 수행

 __userpurge : 스택정리를 callee가 수행

 

함수를 실행전과 후의 스택 주소값을 비교해보면, 

0018FC34 였던 스택 주소가 0x11F8(4,600) 만큼 할당되어

[ 18FC34 - 11F8 = 18EA3C ] 으로 변경되었음을 알 수 있었습니다.

 

어셈블리어로 좀더 자세히 __alloca_probe 함수를 살펴보겠습니다.

지난 실습에서 배운 반복문 for문의 구조가 보입니다.

For문의 조건식은 a1 >= 0x1000 이므로, 두번째줄의 cmp eax, 1000h 명령어로 최초 비교를 수행하고 난 후

JB(Jump if Below) 명령어로 반복문 내부로 진입할지 탈출할지를 결정합니다.

 

아래 보이는 loc_1000122C 은 반복문 내부입니다.

ECX 레지스터와 EAX 레지스터 모두 SUB 명령어를 이용하여 1000h 만큼 뺄셈을 수행합니다.

ECX에서 1000h를 빼는 이유는 For문 내부의 i -= 1000h 코드를 수행하기 위해서이며,

EAX에서 1000h를 빼는 이유는 For문을 한번 실행할때마다 수행되는 증감식 때문입니다.

증감식이 수행되면, 조건식에 의하여 반복문을 빠져나갈지 여부를 결정합니다.

 Tip. MOV vs LEA

 MOV와 LEA의 기능은 비슷합니다. 하지만 LEA에는 장점과 제약이 존재합니다.

 ① 장점 : LEA 명령어는 우변(SRC)의 값을 연산한뒤 좌변(DST)에 옮길 수 있다. ex) LEA EAX, [ESP+1000]

 ② 제약 : LEA의 좌변에는 레지스터만 올 수 있다.

 

위에서 분석한 반복문의 의미는 스택을 4096(1000h) 단위로 연산하기 위함입니다.

따라서 함수에 인자로 전달된 11F8 이라는 값은 4600이므로 반복문을 1회 수행합니다.

반복문을 탈출하고 4600 단위 보다 낮아서 할당되지 않은 잔여 값(504)은 SUB ECX, EAX 명령어로 조정됩니다.

이후 MOV ESP, ECX 명령어로 계산한 스택값을 ESP에 넣어줍니다.

결론 : 이 프로그램은 큰 스택을 사용합니다. (...)

 

__alloca_probe 함수가 끝나고 나면, ebx/ebp/esi/edi 레지스터가 순서대로 push됩니다.

특정함수가 호출되는것도 아니고, 그냥 백업용인가? 생각하여 함수가 리턴되는 끝부분으로 가보니

push한 역순으로 각 레지스터값을 pop 하며 복구하는 부분이 있었습니다. (백업이 맞나봅니다)

 

3) 중복 실행 방지

fdwReason 값이 1인지 CMP 명령어를 이용하여 비교하며, 1이 아닐 경우 loc_100011E8 으로 분기합니다.

이후 이전 문제에서 실습한 Mutex 함수를 이용하여 중복 실행을 방지합니다.

OpenMutex 함수 이전에 실행되는 memset 함수는 4)번 항목에서 분석합니다.

 Tip. DllMain에서 fdwReason의 의미

 ① DLL_PROCESS_ATTACH : 1

 - DLL이 프로세스(클라이언트 프로그램)의 주소 공간에 맵핑될 때 호출

 - 암시적호출 > 프로세스가 시작될 때

 - 명시적호출 > LoadLibrary가 리턴되기 이전에 이 값과 함께 DllMain 호출

 ② DLL_PROCESS_DETACH : 0

 - DLL이 프로세스 주소 공간에서 분리될 때 호출

 - 암시적호출 > 프로세스가 종료될 때

 - 명시적호출 > FreeLibrary 함수에 의해 이 값과 함께 DllMain 호출

 ③ DLL_THREAD_ATTACH : 2

 - DLL을 사용하는 클라이언트 프로세스에서 스레드를 생성할 때마다 이 값과 함께 DllMain 호출

 - DLL에서는 이 값을 받았을 때 스레드별 초기화를 수행해야 한다.

 ④ DLL_THREAD_DETACH : 3

 - DLL을 사용하는 클라이언트 프로세스에서 스레드가 종료될 때마다 이 값과 함께 DllMain 호출

 - DLL에서는 이 값을 받았을 때 스레드별 종료 처리를 한다.

 

 

4) 네트워크, 데이터 송수신

현재 분석중인 악성코드는 데이터 송/수신을 위해 윈속(Winsock) 을 사용합니다.

악성코드는 Server/Client 중에 Client에 해당하므로, bind, listen 등의 함수는 생략되며

WSAStartup > socket > connect > send/recv > WSACleanup 순서로 호출됩니다.

WSAStartup/WSACleanup은 윈속을 사용하기 위해 반드시 호출해야하는 초기화/해제 함수입니다.

 

Hex-ray로 변환된 코드를 보면 아래 스샷의 첫줄에 if( !WSAStartup() ) 코드가 보입니다.

어셈블리어로 살펴보면, 제법 자주나와 눈에 익은 TEST EAX, EAX -> JNZ 명령어 콤보입니다.

이후 socket 함수의 결과값은 CMP ESI, 0FFFFFFFFh 명령어로 -1이 아닌지 비교합니다.

데이터를 송수신하는 과정에서 주목해야할 부분은 inet_addr 함수에 들어가는 고정IP(127.26.152.13)

htons 함수로 변환되어 들어가는 0x50(80) 포트번호입니다. 웹트래픽이 발생하겠군요.

이후 connect 함수의 결과값이 -1인지 확인하기 위해

CMP EAX, 0FFFFFFFFh > JZ 명령어 콤보를 사용합니다. 이번기회에 아예 외워버리겠네요

 Tip. 2의보수

 1의 보수는 단순히 0과 1을 변경하여 음수를 표현합니다.

 하지만 0이 2개가 생기는 문제가 발생합니다. ex) 0000 0000 = 1111 1111 = 모두 0

 이러한 문제의 해결책이 2의 보수 입니다. 1의 보수의 결과값에 1을 더합니다.

 2의 보수를 이용하여 -1을 표현하려면 0000 00001 -> (1의보수) -> 1111 1110 -> (+1) -> 1111 1111

 따라서 위의 코드에서 if(v3 != -1) 을 어셈블리어로 표현할때 CMP ESI, 0FFFFFFFFh 명령어가 나왔습니다.

 

 

본격적으로 while문 내부에서 어떤 통신이 이루어지는지 살펴봅니다.

while문 내부의 조건에 2가지 함수가 위치하고 있습니다.

첫번째는 send 함수로서, 서버측으로 "hello" 문자열을 송신합니다.

두번째는 shutdown 함수로서 네트워크를 종료하는데 사용하는 함수입니다.

shutdown 함수는 close 함수와는 다르게, 옵션을 통해서 연결의 한쪽만 닫을 수 있습니다.

뒤쪽에 아직 recv, closesocket 함수 등이 남아있기 때문에 1(SD_SEND) 옵션을 통해 send 쪽만 닫습니다.

 

서버에 "Hello" 문자열을 보내고 sned 소켓을 닫아버렸습니다. 이후에는 서버의 응답을 기다립니다.

recv 함수의 리턴값은 수신한 바이트 크기이므로 [ 결과값 > 0 ]이면 다음으로 넘어가 문자열 비교를 수행합니다.

TEST EAX, EAX (플래그설정) + JLE(Jump If Less or Equal) (<=) 명령어 콤보로 [ 결과값 <= 0 ]인 경우 분기시킵니다.

이후 서버의 응답을 구분하기 위해 strncmp 함수를 통하여 5(unsigned int) 만큼 문자열 길이를 비교하여 "sleep" 인지 체크합니다.

strncmp 함수는 일치할 경우 0을 리턴하므로, TEST EAX, EAX (플래그설정) + JNZ(Jump If Not Zero) (!=0) 명령어 콤보로

[ 결과값 != 0 ]인 경우, 중략된 코드를 실행하기 위해 분기하고, [ 결과값 == 0 ]인 경우에는 1분간 Sleep 하게됩니다.

 

명령어가 "sleep"이 아닌경우, 분기하여 "exec" 문자열과 비교합니다.

일치하지 않을 경우에는 [ Str==113 ]인지 확인한 후 핸들을 닫지만,

일치한 경우에는 hex-ray 상으로 memset, CreateProcessA 함수를 호출합니다.

 Tip. memset이 없다?

위 어셈블리 코드에서 memset 함수는 rep stosd 명령어로 대체되었습니다.

① rep : 반복적인 작업 수행 시 사용하며, 한번 수행시마다 ECX값 -1씩 감소 ( ECX>0 일때까지 수행 )

② stosd : 4byte(DWORD) 단위로 EDI에 EAX값을 저장하며, 실행 될 때마다 EDI값 +4 증가

이를 바탕으로 위의 어셈블리 명령어를 해석하면

"ECX에 넣어준 11h(17번) 횟수 만큼 EDI에 넣어준 StartupInfo 구조체를 EAX에 넣어준 0 값으로 초기화" 입니다.

4byte 단위로 초기화 하므로 총 68byte를 초기화하는 셈이며, 실제 _STARTINFOA 구조체의 크기(sizeof)를 찍어보면 68입니다.

 

 

이러한 초기화 형태는 3)번 항목의 OpenMutex 함수 실행전에 있던 memset 함수에서도 동일하게 적용됩니다.

다만 그곳에서는 stosw 명령어로 2byte 초기화를 연속해서 수행합니다.

memset 이후에 수행되는 __int16(2byte) 형의 v13 변수 초기화를 수행하기 때문입니다.

char 형 변수인 v14 의 경우에는 [ v14 = 0 = null ] 로 처리되어 별도의 stosb 가 수행되지 않은것 같습니다.(추정)

 

어쨋든, 이러한 초기화 작업이 끝나고 나면

CreateProcess 함수를 통해 특정 프로세스를 실행시킵니다.

여기서 눈여겨 보아야할 것은, 실행시키는 프로세스가 무엇이냐 일텐데,

CreateProcess 함수의 두번째 인수에 들어가는 CommandLine 변수가 어떤 값으로 지정되는지는 아직 알 수 없습니다.

 

지금까지 분석한 DLL의 행위를 정리해보면 아래와 같습니다.

- 큰 스택을 사용한다. (이유는 아직 알 수 없다)

- 뮤텍스를 생성하여 DllMain 안에 있는 코드의 중복 실행을 방지한다.

- WinSock을 이용하여 특정 IP주소(127.26.152.13)와 통신한다.

- WInSock을 이용하여 받은 문자열이 "exec"일 경우, 특정 프로세스를 실행시킨다.

  다만, 아직 어떤 프로세스가 실행될지는 알 수 없다.

 

 

2. Lab07-03.EXE

 

1) 커맨드라인 인자 확인

실행파일의 main 함수를 먼저 살펴보면, 아래와 같이 인자의 개수와 값을 확인합니다.

argc 값이 2가 아니거나, strcmp 결과값이 "WARNING_...." 문자열과 일치 않으면 바로 종료됩니다.

 

문자열을 비교하는 부분은, 분홍색의 라이브러리 함수로 간단하게 표시될줄 알았지만

바이트 단위로 연산을 수행하는 어셈블리 명령어로 되어 있어서, 내부 동작을 살펴볼 수 있었습니다.

strcmp 함수 앞에 !(not) 연산자가 붙어 있다 보니, cmp 결과값이 0이 아니면 바로 점프하는 JNZ 명령어가 있습니다.

비교를 하고난 뒤에 TEST CL, CL + JZ 명령어를 통해 문자열의 끝을 체크합니다.

 Tip. 올리디버거 Dump Window

 argument의 값을 체크하려다가 Code Window에서 보니, 문자열 값이 명령어로 표시되더군요.

 

 확인하고 싶은 값을 Hex 또는 아스키값으로 확인하려면 아래와 같이 Dump Window를 활용합니다.

 

 

2) DLL 파일 생성, 읽기, 복사

현재 분석중인 악성코드는 메모리맵 파일을 이용하여 DLL 파일에 접근하고 있습니다.

파일을 올려 읽는 단계는 아래와 같이 이루어집니다.

① CreateFileA : 파일오픈

② CreateFileMappingA : 파일 내용을 메모리에 올림

③ MapViewOfFile : 메모리에 올려진 파일의 첫번째 주소값을 얻음

이와같은 실행흐름을 통해 Kernel132.dll 파일과 Lab07-03.dll 파일을 메모리에 올리고 있습니다.

이후 어떤 행동을 하는지 살펴봅니다.

 Tip. Symbolic Constant 또는 OllyDbg

 함수에 인자가 많을 경우 일일이 MSDN을 찾아가며 파악하면 시간이 너무 오래 걸리는 경우가 많습니다.

 또한 이전에 한번 파악해두었던 함수의 경우엔 Symbolic constant 기능을 이용하면 빠르게 파악이 가능합니다.

 또한 해당 기능을 통해 상수를 지정해 놓으면, Hex-ray 에서 변환된 코드에서도 동일하게 반영됩니다.

 

 

 IDA에서 일일이 Symbolic constant 를 검색을 통해 일일이 적용하기가 부담스러울 수 있습니다.

 MSDN을 뒤져가며 맞는지 확인해야 하는 경우가 있기 때문이죠.

 이럴땐 OllyDbg를 먼저 참조하는것이 도움이 될 수 있습니다.

 아래 스샷에 보시다시피 우리가 IDA에서 바꾸었던 상수들이 표기되어 있음을 알 수 있습니다.

 

 

이어지는 소스코드는 메모리로 복잡한 읽기와 쓰기가 진행됩니다.

프로그램의 모든 마지막 오퍼레이션까지 확인할 수는 없지만

악성코드의 핵심 기능에서 자주 쓰이는 sub_401040 서브루틴은 어떤 오프셋 계산을 수행하는지

뒤쪽에서 4)번 항목에서 분석합니다.

 

산술연산과 오프셋 계산 과정을 마치면,

메인 하단의 소스코드에서 CloseHandle 함수를 이용하여 파일 편집을 종료했음을 알 수 있습니다.

이후 kernel132.dll 에 Lab07-03.dll 파일을 복사합니다.

kerne132.dll은 kernel32.dll 대신 사용할 것이라고 추측할 수 있지만, 로딩될지 여부는 아직 알 수 없습니다.

주목할만한 사항은 sub_4011E0 함수에 전달되는 "C:\\*" 경로값 입니다.

해당 경로를 어떻게 사용하는지 살펴볼 필요성이 있습니다.

 

 

3) 디렉토리 탐색

sub_4011E0 함수 역시 main과 동일하게 각종 산술연산과 오프셋 계산으로 

어떤 동작을 하는지 파악하기가 어려웠습니다. 그래서 일단 Function Calls 윈도우를 통해

하나씩 차근차근 파악을 해보려 합니다. 주목할만한 단서는 2가지입니다.

① FindFirstFileA, FindNextFileA, FindClose + 경로문자열(C:\\*)

② sub_4011E0(본인/재귀함수)

 

①번을 이용하여 인자값으로 "C:\\*" 경로를 넣어주고

FindFirstFileA, FindNextFileA 함수를 이용하여 코딩하면 아래와 같이 파일을 탐색할 수 있습니다.

해당 함수의 결과값을 보았을때, 재귀함수가 사용되었던 이유는

C드라이브의 모든 디렉토리를 재귀함수를 이용하여 탐색하기 위함으로 생각됩니다.

 

함수의 도입부에서 IF문의 조건을 살펴보면

dwFileAttributes(파일속성) 값이 디렉토리(0x10, FILE_ATTRIBUTE_DIRECTORY16) 이며,

strcmp 함수를 통한 비교 결과가 0이 아닌 경우 진입합니다.

strcmp는 동일할 경우 0을 반환하므로, 비교 문자열이 "." 또는 ".." 이 아닌 경우이죠.

정리하면, 디렉토리일 경우에는 진입, 실행파일인 경우에는 else문입니다.

 

이렇게 진입을 나눠 놓은 이유는 재귀함수 구조를 이용하여 디렉토리를 탐색하기 때문일

가능성이 높습니다. 이를 확인하기 위해 코드를 살펴본 결과, 디렉토리인 경우에는

아래와 같이 본인을 호출하는 코드가 있었습니다.

 

탐색 결과가 실행파일인 경우의 else문을 살펴보면

함수의 마지막 부분에서 stricmp 함수를 통해 ".exe" 를 비교하는 부분이 눈에 띕니다.

EXE파일을 따로 추출하여 어떤 작업을 수행하는 부분은 직관적으로 알 수 있었지만,

IF문 안에 들어간 조건문이 생각보다 까다로웠습니다.

 

stricmp 함수의 첫번째 인자를 계산하는 부분은 LEA EBX, [ESP+ECX+154h+FIndFileData.dwReserved1] 명령입니다.

여기서 ECX는 strlen() 함수를 이용한 cFileName의 결과값입니다.

OR ECX, FFFFFFFF 명령어를 통해 최대값을 넣어준 후 repne scasb 명령어를 이용하여 문자열 길이를 얻어냅니다.

 Tip. IDA의 변수 표현법

 IDA에서는 변수를 표현하는 방법이 다양합니다.

 특히 FindFIleData 구조체는 [esp+154h+FindFileData] 으로 표현되고 있습니다.

 자칫 잘못 생각하면 esp에 계속 주소값이 + 된다고 착각할 수 있지만,

 FIndFileData가 선언된 부분을 살펴보면, 주소값이 ebp 기준으로 [-140h] 입니다.

 결국 [esp + 154h - 140h ] = [esp + 14h] 인 것이죠.

 분석가의 가독성을 높이기 위헤 + 로 표현되어 있지만,

 무심코 머리속으로 플러스(+)만 계산하면 낭패를 볼 수 있습니다.

 

 

 [ESP+154h+FindFileData] 명령어에서 154h가 스택포인터인지 알 수 있는 방법은

 아래처럼 [Options - General - Stack pointer] 옵션을 체크하면 됩니다.

 덤으로 [ Auto comment ] 옵션도 체크해 보았는데, Jump 구문이 해석되어 있어 유용했습니다.

 

 

 

 가독성을 높힌 코드가 아니라, 실제 ESP레지스터 기준의 어셈블리어 명령어를 보려면

 마우스 우클릭을 하여 아래와 같이 변경해주면 됩니다.

 

 

stricmp 명령어의 첫번째 인자에서 dwReserved1 주소값이 들어가는 이유는

아래 그림처럼 4바이트 앞의 주소값에서 시작하여 파일이름의 길이만큼 더하면 확장자만 추출할 수 있기 때문입니다.

(Hex-Ray 코드와 어셈블리코드가 dwReserved0과 dwReserved1을 혼용하고 있으므로, 어셈블리어 기준으로 진행)

 

결과적으로는 재귀함수를 통해 디렉토리를 탐색하며 EXE 파일이 보이면

sub_4010A0 서브루틴을 수행하는 것으로 보이며, 어떤 행위를 하는지 이어서 살펴봅니다.

 

 

4) EXE파일 변조, sub_4010A0()

EXE파일이 검색되면, sub_4010A0 함수에 아래와 같이 경로를 포함한 파일을 인자로 넣고 호출합니다.

분석을 용이하기 위해 notepad.exe 파일을 C:\ 경로에 미리 옮겨 놓았습니다.

 

MapViewOfFile 함수를 이용하여 메모리맵 파일의 Starting Address를 이용하여 PE Signature를 체크합니다.

주소값을 이용하기 때문에 중간중간 IsBadReadPtr 함수를 이용하여 포인터의 유효성을 검사합니다.

 Tip. "[ ]" 연산자를 이용한 주소값 계산 [1]

 ptr이 임의의 배열을 가리키는 포인터이고, n이 정수일때 ptr[n] = *(ptr+n) 이 성립합니다.

 즉, 위에서 *((_DWORD *)result +15) 코드에서, result 변수는 void 형이기 때문에

 사용과 동시에 (_DWORD *) 포인터형으로 캐스팅 되었고, "[]" 연산자를 사용할 수 있습니다.

 따라서 4byte(DWORD) 단위로 계산되어, ImageBase에서 60byte 떨어진 곳에 위치하는  

 _IMAGE_DOS_HEADER 구조체의 e_lfanew 멤버를 가리키게 됩니다.

 e_lfanew는 NT header의 오프셋을 가지므로, 

 (int)(char *)result + *((_DWORD *)result +15) 를 통하여 

 _IMAGE_NT_HEADERS 구조체의 Signature 멤버가 PE(45 50 00 00, 17,744) 인지 체크할 수 있습니다. 

 

"PE" 시그니처가 확인되면 sub_401040 함수에 인자 3개를 넣어줍니다.

① [arg1] : 7604 : *(_DWORD *)(v5 + 128) = *(_DWORD *)(3D0160) = Import Directory RVA

② [arg2] : v5 : 3D00E0 = ImageBase + E0 = NT헤더 시작주소 (PE Signature)

③ [arg3] : v2 : 3D0000 = ImageBase

 Tip. "[ ]" 연산자를 이용한 주소값 계산 [2]

 위의 "[]" 연산자와 동일하게 생각하여 v5가 4byte(int) 단위라는 생각에

 무심코 128*4 = 512 주소값을 더하여 계산하면 낭패를 보게됩니다.

 v5는 포인터형이 아닌 int 형이므로, "[]" 연산자의 조건이 성립하지 않습니다.

 따라서 (v5 + 128)의 의미는, v5에 저장된 정수(실제로는 주소)에 128을 더하는 연산입니다.

 OllyDbg로 확인해보면 위와 같이 EBP+80h(128) 으로 계산되는 부분을 확인할 수 있습니다.

 

해당 인자값들을 이용하여 어떤 값을 반환하는지 알아보기 위헤 sub_401040 서브루틴을 살펴봅니다.

함수 내부를 살펴보면, 또다시 매개변수 a1, a2를 이용하여 sub_401000 서브루틴을 실행합니다.

특히 리턴값이 result = a3 + a1 + *(_DWORD *)(result + 20) - *(_DWORD *)(result + 12) 계산식이므로,

sub_401000 의 결과값을 알지 못하면 해석이 불가능합니다.

 

sub_401000 서브루틴으로 한단계 더 깊숙히 들어가봅니다. 중간의 while 구문이 함수의 핵심 기능인것 같습니다.

while 문은 한번 반복할때마다 Import Directory RVA 값과 RVA(섹션시작주소) + VirtualSize(섹션크기) 값을 비교하여

Import Directory RVA 값이 더 크면 result 에 40을 더합니다.

이것이 의미하는 바는, Import Directory RVA 즉, IID가 존재하는 섹션의 헤더를 찾겠다는 의미입니다.

만약 IID가 포함된 섹션이 아니라면, IMAGE_SECTION_HEADER 구조체의 크기인 40씩 더하여

다음 섹션헤더로 넘어갑니다. 반복문에서 탈출하면 계산된 섹션헤더의 주소값을 리턴합니다.

sub_401000 함수의 기능을 정리해보면 아래와 같습니다.

> NT헤더 시작주소(Signature)를 첫번째 인자로 받아서, 두번째 인자의 RVA 주소가 위치하는 섹션 헤더를 찾아 반환

 Tip. sub_401000 서브루틴 주요 변수

 코드를 해석하기 위해 계산한 변수값들은 아래와 같습니다. (굵게 표시된 부분이 RVA)

 ① v3 = 3 (NumberOfSerctions)

    # *(_WORD *)(a2 + 6) = *(_WORD *)(3D00E0(a2) + 6) = *(_WORD *)(3D00E6) = 3

 ② result = 3D001D8 (Section Header Offset, Opiotnal Header 오프셋 + 헤더크기)

    # Opiotional Header Size : *(_WORD *)(a2 + 20) = *(_WORD *)(3D00E0+ 20) = *(_WORD *)(3D00F4) = E0

    # Optional Header Offset : a2 +24 = 3D00E0 +24 = 3D00F8 =NT헤더 오프셋 + NT헤더 크기

 ③ v5 = 1000 (Virtual Address, 메모리에서 섹션의 시작 주소, RVA)

    # *(_DWORD *)(result + 12) = *(_DWORD *)(3D001E4) = 1000

 

이제 sub_401000 서브루틴의 리턴값이 IID가 포함된 섹션헤더의 주소임을 알았습니다.

sub_401040 함수에서 분석하지 못했던 나머지 부분을 다시 살펴보면 아래와 같습니다.

result = a3 + a1 + *(_DWORD *)(result + 20) - *(_DWORD *)(result + 12)

이것을 sub_401000 함수의 리턴값으로 분석해보면 아래와 같습니다.

result = 3D0000(ImageBase) + 7604(RVA) - 1000(VA) + 400(Pointer to Raw Data) : 3D6A04 

해당 공식은 RVA 값을 이용하여 File Offset 을 구하는 공식입니다.

결과적으로 sub_401040 서브루틴의 주요 기능을 정리하면 아래와 같습니다.

> RVA, NT헤더 시작주소(PE Signature), RVA를 인자로 받고, 해당 RVA의 파일 오프셋을 게산하여 반환

 Tip. sub_401040 서브루틴 주요 변수

 result = 3D6A04 (File Offset)

    # result = 3D0000(ImageBase) + 7604(RVA) - 1000(VA) + 400(Pointer to Raw Data) : 3D6A04 

    #  *(_DWORD *)(result + 20) = *(_DWORD *)( 3D001D8+ 20)  = *(_DWORD *)(3D001EC) = 400 (Pointer to Raw Data)

    # *(_DWORD *)(result + 12) = *(_DWORD *)( 3D001D8+ 12) = *(_DWORD *)(3D001E4) = 1000 : (VA)

 

for( i = (int)((char *)v6 + 12); ; i +=20) 코드의 의미는 20byte 단위의 IID(IMAGE_IMPORT_DESCRIPTOR) 구조체에서

12byte 에 위치하고 있는 Name 멤버를 변수 i 에 할당한 후

stricmp 함수로 "kernel32.dll" 문자열을 비교하기 위해 수행하는 반복문입니다.

 

For문 내에서도 sub_401040가 또한번 호출되고 있음을 볼 수 있는데,

IID구조체의 첫번째 변수가 Import Name Table RVA 값을 가지기 때문에

이 역시 파일 오프셋 값으로 변환해야되기 때문입니다.

해당 악성코드가 왜 자꾸 RVA 값을 파일 오프셋으로 변환하는지 알아낼 필요가 있습니다.

 

문자열 비교 후에 do while 문으로 반복을 수행하는 것이 보입니다. 해당 부분은

REPNE SCASB 명령어로 문자열의 길이를 얻는 코드로서, 어셈블리 명령어로 보는것이 가독성이 빠릅니다.

길이를 계산한 이후에는 memcpy 명령어를 이용하여 IID의 Name 멤버의 "kernel32.dll" 문자열을

Lab07-03.dll의 복사 파일인 "kernel132.dll" 문자열로 패치합니다.

실행파일이 임포트하는 DLL을 조작하는 핵심코드이며, 이를 위해서 RVA -> FileOffset 변환이 필요했습니다. 

 Tip. 문자열길이 구하기 : REPNE + SCASB

 해당 명령어의 의미는 아래와 같습니다. 

 - rep : ecx > 0 인 동안 명령어 반복

 - repne : Zero Flag 가 1이고, ecx >0 인 동안 명령어 반복

 - scasb/scasw/scasd ptr : 단위별로 EAX와 ptr 값을 비교

 이것을 이용하여 memcpy 에서 사용되는 v12 변수의 문자열 길이를 구하는 부분을 살펴보면

 MOV EDI, EBX 명령어를 통해 EDI에 문자열을 입력하고 난 후

 OR ECX, FFFFFFFF 명령어를 통해 ECX 값을 최대치로 설정해둡니다.

 REPNE SCAS [EDI] 명령어를 통해 EDI에 저장된 문자(byte, word, dword 단위)와 EAX(=0) 값을

 비교하여 동일한 값이 아니면 [ECX = ECX -1] , [EDI = EDI +1] 연산을 반복합니다.

 EDI에 저장된 문자열의 끝의 Null(=0x00)을 만나거나, ECX의 값이 0이 되면 루틴이 종료되며, 

 마지막에 계속 -1씩 깍던 ECX의 값을 NOT 연산자로 반전시켜 문자열의 길이를 얻습니다.

 

 

패치 이후에는 [v5 + 208], [v5 + 208 + 4] 주소에 있는 값들을 0을 초기화 시킵니다.

해당 위치는 BOUND IMPORT_Directory_Table(BIT) 영역인데, 왜 0 값으로 설정할까요?

리버싱 서적인 나뭇잎 책에서는 패치를 통한 DLL Injection 부분에서

"BIT는 DLL 로딩 속도를 향상시킬 수 있는 기법이며, 그냥 놔둬도 문제 없는 경우가 많지만

인젝션을 테스트할 때 BIT 때문에 정상 동작하지 않아서 0으로 설정 한다" 는 내용이 있었습니다.

아마 우리가 분석중인 악성코드도 정상 실행을 보장하기 위해 해당 코드를 넣지 않았을까 생각됩니다.

모든 작업이 종료되면 UnmapViewOfFile, Close Handle 함수 등으로 할당받은 자원을 해제합니다.

 

지금까지 분석한 EXE의 행위를 정리해보면 아래와 같습니다.

- 메모리맵 파일을 이용한 DLL 복사

- 디렉토리를 탐색하여 EXE파일 검색

- EXE 파일의 IID에서 Name 멤버값이 "kernel32.dll" 인 경우 오프셋 계산

- 반환된 오프셋을 이용하여 정상 DLL의 이름을 악성코드 DLL로 패치

 

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

3. 문제풀이

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

 

1) 이 프로그램은 어떤 방식으로 컴퓨터가 재시작할 때마다 실행을 보장하는가?

이 프로그램은 C:\\Windows\System32에 DLL을 복사해서 영구적으로 감염시키고,

C드라이브의 모든 EXE 파일이 해당 DLL을 임포트하도록 변조합니다.

 

2) 이 프로그램을 탐지할 때 호스트 기반으로 좋은 시그니처는 무엇인가?

프로그램은 "kernel132.dll" 파일명으로 하드 코딩되어 있으므로,

호스트기반의 시그니처로 사용할 수 있습니다.

 

3) 이 프로그램의 목적은 무엇인가?

프로그램의 목저은 삭제하기 어려운 원격 호스트 접속을 가능하게 만드는 백도어를 생성하는데 있습니다.

백도어는 두 명령어를 가지는데, 하나는 명령어를 실행시키는 "exec" 이며, 나머지는 "sleep" 입니다.

 

4) 일단 악성코드가 설치된다면 어떻게 삭제할 수 있는가?

해당 프로그램은 C드라이브의 모든 exe 파일을 감염시키므로 매우 삭제하기 힘듭니다.

이런 경우는 백업해서 복구하는게 가장 좋으며, kernel32.dll의 이름을 kerne132.dll로 변경하면

임시적인 대처를 할 수 있습니다.

 

 

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

4. 마무리

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

이번 문제는 어디까지 분석을 진행하느냐에 따라 매우 분량이 커질 수 있다고 생각합니다.

실제로 오프셋을 계산하는 많은 부분들을 생략했음에도 불구하고,

지금까지 분석한 실습 악성코드중 가장 많은 포스팅 내용이 나왔습니다.

내용이 많아 오타 또는 잘못된 내용이 있을 수 있으므로,

댓글 남겨주시면 확인 후 수정하겠습니다.

 

By Red_Message.

 

posted by Red_Message

안녕하세요. Message입니다.

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

악성코드의 분량은 얼마 되지 않았지만.. 익숙하지 않은 내용들로 인해 시간이 많이 걸렸습니다.

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

 

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

0. 기초 동적 분석

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

문제풀이에 앞서 간단한 동적 분석을 진행합니다.

 

1) PE구조 & 패킹체크

별도의 패킹이 되어 있지 않습니다.

 

2) DLL 체크

ole32.dll, OLEAUT32.dll, MSVCTR.dll 총 3개의 DLL을 임포트합니다.

MSVCRT.dll에서 가장 많은 13개의 API를 임포트하고 있습니다.

 

- ole32.dll

3개 API 모두 생소합니다. 책에서는 COM과 관련된 API라고 되어있지만

COM 자체가 다뤄보지 않은 영역이다보니 개념이 잘 잡히지 않더군요.

 Tip. COM

 위키백과 : 컴포넌트 오브젝트 모델(Component Object Model, COM)은 마이크로소프트가 개발한

 소프트웨어 구성 요소들의 응용 프로그램 이진 인터페이스이다.

 COM을 이용해 개발된 프로그램들은 프로세스간 통신과 동적 오브젝트 생성이 가능하다.

 + 여러 컴포넌트 객체를 이용하여 프로그램을 개발하는 모델을 의미

 실습교재 : 이종의 소프트웨어 컴포넌트에서 상호 세부내용을 모르더라도 서로 다른 코드를

 호출할 수 있게 하는 인터페이스 표준이다. COM을 이용하는 악성코드를 분석할 때

 COM 함수 호출의 결과로 어떤 코드가 실행될지 알 필요가 있다.

 

- OLEAUT32.dll

Name에는 Ordinal 값만 적혀있으며, Hint가 N/A로 비어있네요.

DWalker로 살펴보았더니, N/A로 비어져 있는건 똑같지만

Ordinal 값에 해당하는 함수는 아래 스샷과 같이 보기 좋게 표기되어 있었습니다.

해당하는 API는 SysAllocString(0x0002), SysFreeString(0x0006), VariantInit(0x008) 이군요.

SysAllocString : COM에서 다루는 스트링인 BSTR생성 (VC++에서 유니코드 문자열은 BSTR타입으로 표시)

② SysFreeString : 할당한 BSTR 해제

③ VariantInit : COM에서 사용하는 VARIANTARG(or VARIANT) 구조체 초기화

 

- MSVCTR.dll

앞에 [ _ ] 문자가 1~2개씩 붙어있는 API 들이 많습니다.

검색해보니, 아래와 같이 나와있더군요.

"밑줄이 붙는 것은 MS 확장 키워드이며, 밑줄 한개의 경우는 하위 호환성을 위해 남겨져 있을 뿐 2개가 정식 표기"

"C++ 의 표준 키워드에 MS가 약간의 의미변경 or 기능추가한 경우, 맡줄을 추가하여 컴파일러가 판단하는 기준으로 사용"

별거 아닐 수 있지만...모르면 찜찜하니까요.

 

 

3) String 체크

지금까지의 악성코드 실습파일중 역대급으로 출력되는 스트링이 없네요.

.rdata 영역에 dll 이름만 덩그러니 놓여 있습니다.

 

뭔가 허전하기도 해서, 지난번 Tip을 복습할겸 .rdata 영역에 대해서 다시 보았더니...

>> .rdata : 프로그램 내의 전역에서 접근 가능한 읽기 전용 데이터를 담고 있음.

>> .idata : 존재 시 임포트 함수 정보를 저장하고 있으며, 존재하지 않는다면 .rdata 섹션 내의 임포트 함수 정보에 저장

그래서 .idata가 정말 없나? 하고 CFF로 구조를 살펴보니 정말 .idata 섹션이 없네요!

 

 

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

1. 이 프로그램은 어떤 방식으로 지속 메커니즘을 보장하는가?

2. 이 프로그램의 목적은 무엇인가?

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

일단 악성코드를 실행해 보면 특정 URL의 ad.html 페이지가 뜨게됩니다.

웹페이지의 이름으로 미루어보건데, 광고페이지로 추정됩니다.

 

Hex-ray 기능을 이용하여 해당 악성코드의 main을 살펴보면

별도의 지속성을 위한 메커니즘이 보이지 않으며, 굉장히 짧은 코드내용을 가지고 있습니다.

 

어셈블리코드를 보면서 찬찬히 분석을 해봅니다.

COM을 사용하는 각 스레드는 다른 COM 라이브러리 함수 호출 전에 적어도 한번은

OleInitialize나 CoInitializeEx 함수를 호출해야합니다.

현재 분석중인 악성코드 역시 OleInitialize 함수를 호출하고 있으며,

이후에 CoCreateInstance에 RCLSID, RIID, PPV 등의 인자값을 넣어주며 COM 기능에 접근합니다.

RCLSID : 클래스식별자 / 생성하고자 하는 컴포넌트의 CLSID

② RIID : 인터페이스식별자 / 얻고자 하는 컴포넌트의 인터페이스

③ PPV : 객체 인터페이스를 받을 수 있는 포인터

 

악성코드는 COM에 접근하며 넣어주는 클래스식별자(CLSID)는 0002DF01-0000-0000-C000-000000000046 입니다.

CLSID값이 의미하는 것이 무엇인지 알아내려면 레지스트리 HKLM∖SOFTWARE∖Classes∖CLSID 에서 찾아보아야 합니다.

LocalServer32Internet Explorer 경로가 존재하므로,

CoCreateInstance가 호출될때 로드할 실행 파일임을 유추할 수 있습니다.

 

인터페이스식별자(RIID)로 넣어주는 값은 0D30C1661-0CDAF-11D0-8A3E00C04F0C90E26E 입니다.

해당값은 검색해 보았더니 MSDN에서 친절하게 알려주더군요!

 

CoCreateInstance 함수가 성공적으로 동작하게 되면, PPV로 명명한 변수 내의 스택에 저장되며

COM의 기능을 사용하기 위해 인자값으로 사용될 변수(URL 등)들을

VariantInit 함수와 SysAllocString 함수를 이용하여 세팅합니다.

 

COM의 기능을 호출하는 부분은 0x401074 주소입니다.

하지만 지금까지 편리하게 분홍색으로 표시해주는 API들과는 달리

명령어 call dword ptr [edx+2Ch] 로 표기되어 있습니다. 단번에 어떤 기능을 호출하는지 파악하기 어렵습니다.

악성코드 프로그램이 COM 함수를 호출했을 때 무슨 일이 일어나는지 인지하기 위해

IDA Pro의 구조체 서브뷰(SubView)에서 [INSERT - Add standard structure] 기능을 이용합니다.

 Tip. Structure 기능 활용하기

 구조체 표기를 변경하기 위해 퀵뷰에서 Structure를 선택합니다.

  

 

 우리가 필요한 구조체는 CoCreateInstance 함수를 호출할때 인자값으로 넣어주었던

 인터페이스식별자, 즉 IwebBrowser2 이므로, 해당값으로 검색해줍니다.

 검색결과는 IwebBrowser2②IwebBrowser2Vtbl 2개가 나옵니다.

 결과적으로 ①번은 오프셋이 나오지 않았고, ②번을 추가했더니 정상적으로 명명이 됐습니다.

 아마 오프셋을 명명하는데 필요한 부분이 IwebBrowser2 구조체 자체가 아니라

 가상 포인터 테이블 목록(VTBL, Virual Function Table)이 필요해서가 아닐까 추측합니다.

 

 

 이후에는 2Ch에 마우스 우클릭을 하면, 아래와 같이 오프셋을 명명할 수 있습니다.

 

 

 

변경하고나니 아래처럼 스택에 푸시되는 인자값들의 설명도 자동으로 표기됩니다. 

이후에 SysFreeStringOleUninitialize 등을 호출하며 main이 종료됩니다.

 

 

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

3. 이 프로그램은 언제 실행을 종료하는가?

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

결과적으로 COM 기능을 이용하여 광고 웹페이지를 띄운 후 실행을 종료합니다.

 

posted by Red_Message

안녕하세요. Message입니다.

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

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

 

 

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

0. 기초 동적 분석

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

문제풀이에 앞서 간단한 동적 분석을 진행합니다.

 

1) PE구조 & 패킹체크

별도의 패킹이 되어 있지 않습니다.

 

2) DLL 체크

KERNEL32.dll, ADVAPI32.dll, WININET.dll 총 3개의 dll을 임포트합니다.

눈여겨 보지 않았었는데, 각 dll별로 임포트하고 있는 숫자를 CFF에서 표기해주는군요.

각 DLL에서 43개, 3개, 2개의 API를 임포트하고 있습니다.

 

- KERNEL32.dll

항상 가장 많은 API들을 임포트하고 있어서 그런지, 딱 보았을때 어떤 API를 이용하여

어떤 악성행위를 하는지 가장 감이 오지 않습니다.

 

- ADVAPI32.dll

서비스 관련 API들이 보입니다. 아마 백그라운드에서 동작할 수 있음을 염두해둡니다.

 

- WININET.dll

지난번의 문제들과 동일하게 Internet 연결 관련 API들이 보입니다.

 

 

3) String 체크

IDA의 String Window(Shift+F12)를 보면 아래와 같이 .data섹션(초기화된 전역변수, 읽기/쓰기 가능) 에서

MalService, 악성URL, IE와 버전 등의 스트링값이 존재합니다.

 

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

1. 이 프로그램은 어떤 방식으로 컴퓨터가 재시작할 때마다 실행(지속 메커니즘)을 보장하는가?

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

악성코드를 호출하면 main에서 가장 첫번째로 호출하는 함수가 바로 StartServiceCtrlDispatcher API입니다.

실전 악성코드 책에 있는 악성코드를 분석하면서, 서비스에 등록되는 악성코드 실습을 이미 해봤기에

그냥 비슷하거나 동일한 케이스라고만 막연히 생각하였는데, 가만보니 처음보는 API였습니다.

그래서 지난 실습을 검색하여서, 어떤 차이점이 있나 확인해보았습니다.

- 실습3-2 URL : http://redscreen.tistory.com/13

 

결론적으로 주요 골자는 아래와 같습니다.

"서비스는 WinLogon.exe가 호출하는 Services.exe(SCM:서비스제어관리자)에 의해 관리되지만

예외적으로 DLL 기반의 서비스는 svchost.exe에 의해 관리된다"

지난번엔 DLL기반의 서비스를 분석하였고, 오늘은 SCM이 관리하는 서비스에 관한 내용을 살펴봐야 합니다.

 

main 어셈블리 코드를 살펴보면 아래와 같습니다.

아직 악성코드가 어떤 방식으로 실행되어지고, 서비스가 등록되는지 파악은 안되지만

"MalService" 라는 서비스를 만들어 동작하고 있음을 확인되었습니다.

 

 

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

2. 이 프로그램은 왜 뮤텍스를 이용하고 있는가?

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

짧은 메인에서 StartServiceCtrlDispatcherA API를 호출하고 난 이후에 바로 sub_401040 서브루틴을 호출합니다.

해당 서브루틴은 아래와 같이 OpenMutexA API를 호출하고

함수가 종료된 이후에 값이 0인지 확인하는 TEST EAX, EAX 명령어를 이용해 프로세스 종료 혹은 진행을 결정합니다.

특이한점은, "HGL345" 라는 이름의 뮤텍스를 오픈해서 핸들을 정상적으로 가져왔을 경우에

왼쪽으로 분기하여 ExitProcess를 호출하며 프로세스를 종료시키는 점입니다. 

 

만약 해당 뮤텍스가 존재하지 않는다면, 오른쪽으로 분기하여 아래와 코드를 실행합니다.

기존에 있는 뮤텍스에 접근하는것이 아니라, CreateMutexA API를 이용하여

방금 시도했던 "HGL345" 뮤텍스를 새로 생성합니다.

이런 코드구조로 실행되는 이유는 특정 시간에 시스템에서 실행 파일 사본이 하나만 동작하게 보장하기 위해서입니다.

만약 이미 악성코드가 수행중이라면, 바로 위의 OpenMutexA 함수 호출을 성공하면서, 프로세스가 종료됩니다.

 

사실 뭔가 내용은 많아보이지만, Hex-ray 상으로 살펴보면, 그냥 스쳐지나가는 체크일뿐입니다.

이후에 맨아래의 CreateServiceA를 호출하기 위해

OpenSCMManagerA, GetCurrentProcess, GetModuleFileNameA API를 순차적으로 호출합니다.

OpenSCMManagerA : 프로그램이 서비스를 추가하거나 수정할 수 있는 서비스 제어 관리자 핸들 반환

② GetCurrentProcess : 현재 프로세스의 핸들 반환 (근데 왜 실행했는지는 모르겠네요)

③ GetModuleFileNameA : 첫째 인자가 0 인 경우, 현재 동작중인 실행 파일이나 로드된 DLL의 전체 경로명 반환

Tip. API 뒤에 붙은 A or W는 String을 다루는 API임을 알려줍니다. A는 ANSI를, W는 UNICODE를 의미합니다.

 

CreateServiceA API를 호출하기 위해서는 아래처럼 많은 인자값들이 필요합니다.

그중에 주요한 인자만 정리하고 넘어갑니다.

- hSCManager : 서비스 실행에 필요한 SCM / ①에서 얻은 SCM 핸들

- dwServiceType : SERVICE_WIN32_OWN_PROCESS(0x10)

        ※ SERVICE_KERNEL_DRIVER(0x01) / SERVICE_FILE_SYSTEM_DRIVER(0x02) / SERVICE_ADAPTER(0x04) / SERVICE_RECOGNIZER_DRIVER(0x08)

- dwStartType : 시스템 시작 시 자동 시작 / SERVICE_AUTO_START(0x02)

       SERVICE_BOOT_START(0x00) / SERVICE_SYSTEM_START(0x01) / SERVICE_DEMAND_START(0x03) / SERVICE_DISABLED(0x04)

- lpBinaryPathName : 실행파일의 바이너리 경로 / ③에서 얻은 경로

 

서비스함수를 실행한 이후에는 시간과 관련된

SystemTimeToFileTIme, CreateWaitableTimerA, SetWaitableTimer, WaitForSingleObject API들을 순차적으로 실행합니다.

여기서 중요 포인트는 WaitForSingleObject API입니다.

 

아래 Hex-ray 결과에서 알 수 있다싶이 WaitForSingleObject의 결과값이 0이되면

20번 반복수행되는 CreateThread가 동작합니다.

WaitForSingleObject의 인자값을 넣어주기 위해서 CreateWaitableTimerA, SetWaitableTimer 등을 실행합니다.

SystemTimeToFileTIme : 시스템 타임 --> 타임 포맷으로 변환 / ③의 인자값으로 사용하기 위해

② CreateWaitableTimerA : waitable 타이머 객체 생성( 생성시 Non-Signaled 상태 ) / ①의 결과값을 인자로 사용

③ SetWaitableTimer : waitable 타이머 객체에 알람 시간 설정 ( 알람 시간이 되면 Signaled 상태 ) / ②의 결과값을 인자로 사용

WaitForSingleObject : 넣어준 waitable 타이머 객체가 Signaled 상태가 되면, WAIT_OBJECT_0(0x00000000L) 반환

Tip. 자료형에 따른 접미사

 

SystemTime.wYear에 2100을 할당함으로서, 2100년 1월 1일이 되어

반환값이 WAIT_OBJECT_0(0x00000000L)이면 20번의 CreateThread를 수행하게됩니다.

CreateThread안에는 StartAddress 라는 함수가 들어있는데,

InternetOpenA -> InternetOpenUrl 순으로 "http://www.......book.com" URL에 IE8을 이용하여

반복적으로 접근을 시도합니다. 20개의 스레드가 동작하므로 상당한 트래픽이 유발될 수도 있습니다.

DDoS 공격을 위한 악성코드가 이런식으로 구성되는구나...싶었습니다.

 

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

3. 이 프로그램을 탐지할 때 호스트 기반으로 좋은 시그니처는 무엇인가?

4. 이 악성코드를 탐지할 때 네트워크 기반으로 좋은 시그니처는 무엇인가?

5. 이 프로그램의 목적은 무엇인가?

6. 이 프로그램은 언제 실행을 종료하는가?

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

3. 호스트기반의 좋은 시그니처는 "MalService"라는 서비스와 "HGL345"라는 이름의 뮤텍스입니다.

4. 네트워크 기반의 시그니처는 IE8.0과 URL입니다.

5. 프로그램의 목적은 특정 시간대에 수행되는 DDoS 공격입니다.

6. 종료되지 않으며, 2100년 1월 1일부터 20개의 스레드를 동작시켜 무한루프로 동작합니다.

posted by Red_Message

안녕하세요. Message입니다.

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

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

 

 

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

1. 실습 6-3과 6-4의 main 함수에서 호출한 함수 간의 차이점은 무엇인가?

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

 

[Flow Chart]를 이용하여 main의 구조를 살펴보면,

지난 문제들과는 구조가 약간 상이함을 알 수 있습니다.

기존의 0x401000(인터넷 연결 확인 함수), 0x401040(HTML파싱), 0x4012B5(printf) 등은 동일합니다.

 

Tip. 주석 남기기

기존에 분석한 함수의 기능을 빨리 파악하기 위해 주석을 남기는게 좋습니다.

- 명령어 옆에 코멘트 : 단축키 [ : ]

- 라인추가 : 단축키 [ INS ], [ Shift+INS ] (코드 위 아래로)

 

 

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

2. 어떤 새로운 코드 구조가 main 함수에 추가됐는가?

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

 

그래프상에서 아래에서 위로 향하는 굵고 파란 화살표가 눈에 띕니다.

바로 반복문을 뜻하는 화살표입니다.

 

어떤 반복문이 추가되었는지 hex-ray 기능을 이용하여 살펴보면

아래와 같이 for문이 추가된것을 알 수 있습니다.

 

어셈블리코드에서 살펴보면,

main 초반에 인터넷 연결을 확인한 이후에 바로 반복문에 진입합니다.

만약 인터넷 연결이 되어있지 않다면,

XOR EAX, EAX 명령어로 Overflow Carry 플래그를 청소한 뒤 loc_4012B1 으로 분기합니다.

 

이후부터 [ebp+var_C]에 0을 할당하게 되는데, 여기서 var_C 변수는 반복 카운터에 사용됩니다.

초기에 0 으로 설정된 이후에, 바로 아래에 있는 loc_401251 에서 add 명령어를 통해 +1씩 증가합니다.

for문이 종료되는 시점은 loc_40125A 에서 cmp [ebp+var_C], 5a0h(1440) 명령어의 결과값이 (op1 - op2)

0 이상이면 jge(greater or equal, <=) 명령어에 의하여 loc_4012AF 주소로 분기하게 됩니다.

 

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

3. 이 실습의 HTML 함수 파싱이 기존 실습과 어떤 차이점이 있는가?

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

기존 HTML 파싱을 수행했던 0x401040 서브루틴의 경우 인자값이 없었습니다.

하지만 지금 실습중인 악성코드는 for 문의 var_C 변수를 인자값으로 받습니다.

해당 인자값이 어떻게 사용되는지 살펴보면 아래와 같이 sub_401040의 매개변수 a1으로 선언되어

sprintf 함수의 3번째 인자로 사용됩니다.

 

sprintf 함수로 인하여 Dest 변수에 입력된 "Internet Ex..../Pma%d" 문자열은 다시

InternetOpenA API의 첫번째 인자인 User-Agent 값에 들어가게 됩니다.

결국 0x401040에 넣어주는 인자값은, 서버에 접속할때마다 Uger-Agent 값을 +1 씩 변경할 것이고

서버측에서는 클라이언트의 Uger-Agent 값을 통해 얼마나 오래 감염된 PC인지 추정할 수 있는 근거가 될것입니다.

 

 

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

4. 프로그램이 얼마나 오래 동작하는가? (인터넷에 연결돼 있다고 가정)

5. 이 악성코드에서 네트워크 기반의 행위가 존재하는가?

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

얼마나 동작하는지 알아내기 위해, Sleep 함수가 있는곳으로 가보겠습니다.

Sleep 함수에 입력되는 인자값은 0EA60h(60,000) = 60초 입니다.

push되는 "0EA60" 값이 문자열스럽지만, 계산기로 16진수 계산하시면 정확합니다.

for문은 1440번 반복되므로, 60이 곱해지면 자연스럽게 1440분이 됩니다.

1440분 = 24시간 이므로, 하루동안 동작하는 프로그램입니다.

 

네트워크 기반의 행위는 매번 변경되는 User-Agent 값이 되겠습니다.

 

 

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

6. 이 악성코드의 목적은 무엇인가?

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

전 문제와 동일하게 인터넷 연결 여부, HTML 파싱등을 수행하나,

증가되는 User-Agent 값을 통하여 클라이언트를 관리할 수 있는 기능이 추가되었습니다.

 

posted by Red_Message