RNRF 2021. 11. 3. 21:41

* 메타스플로잇 내부 구조
: 이번 시간에는 메타스플로잇의전체적인 구조를 살짝 알아보고 간다. 내부 구조화 개발이라고 해서 이러한 내부 구조가 어떻게 개발에 응용될 수 있는지와 모듈 개발을 하거나 어떠한 메타스플로잇에서 기능을 추가하려고 할 때 어떠한 부분을 참고 하면 되는지와 지금 어떠한 기능을 가져와서 사용해야 원하는 목적을 이룰 수 있을지에 대해서 설명하고 이해해본다
-> 우선 메타스플로잇의 내부 구조는 아래의 그림과 같다

-> 이러한 방식으로 되어있는 그림이 있는 이유는 운영체제를 공부할 때나, 안드로이드 아키텍처를 볼 때 이러한 식의 계층용 구조를 많이 보는데, 개념적으로는 조금 다를 수 있지만 프레임워크 자체도 계층형으로 볼 수 있기 때문에 이러한 그림을 그릴 수 있는것이다
->> 사용자와 가장 가까이 있는 "interface"부터 시작해서 그 밑단에 있는 "modules"와 그 밑단에 있는 "library"로 구성되어 있다. 인터페이스 같은 경우에는 크게 세 가지가 있는데, 메타스플로잇 커뮤니티 버전에서는 "msfconsole", "armitage" 두 가지가 사용 가능하다. "msfconsole"은 검은 화면에 있는 명령 프로포트 기반이고, "armitage"는 gui 기반으로 되어있다. 보통 둘 중 msfconsole을 많이 쓸 것이다. 이러한 "msfconsole" 안에서 "modules"에 있는 모드들을 가져다 쓸 수 있다. 물론 이러한 msfconsole을 통하지 않고 그냥 코드를 직접 짜서 할 수도 있겠지만, 그것은 나중에 개발 과정을 이해하면 가능할 것이다. 그리고 밑단의 "modules"의 "exploits" 모듈 같은 경우에 실질적으로 무언가 취약점을 가지고 상대방의 시스템을 공격하는 공격 코드이고, "auxiliary" 모듈 같은 경우에는 어떠한 것을 스캔하거나 도스? 기능을 하는 등의 정보 수집 또는 페이로드가 필요하지 않는 공격을 하는 공격 코드라고 할 수 있다. 그리고 "payloads" 모듈은 최종 목적 코드가 되는 부분이다. 예를 들어서 "shell"을 맺는다거나, 파일을 업로드 한다거나, 다운로드 하거나 등등의 부분이다. "post" 모듈 같은 경우에 페이로드와 약간 애매한 포지션이 있다. "post"도 하나의 모듈이지만, 궁극적인 목적 자체가 익스플로잇이 성공한 다음에 공격하는 공격 코드를 담고 있는 내용으로서 어떻게 보면 페이로드가 하는 역할과 비슷할 수 있지만 단위가 다르다고 할 수 있다. 같은 모듈 수준에 있지만 크게 보면 "exploits"와 "auxiliary"와 "post"가 하나의 독립적인 기능을 하는 모듈이라고 본다면 "payloads", "encoders", "nops"는 위의 세 가지 모듈이 잘 돌아갈 수 있도록 해주는 하나의 구성 요소 같은 개념이다. 그렇지만 독립적으로도 사용할 수 있기 때문에 모듈이라는 단위를 입혀 놓았다고 생각하면 편하다. 인코딩은 페이로드를 인코딩하는 역할이고, nop는 어떻게 보면 인코딩의 목적과 똑같은데 페이로드 중간에 의미 없는 공격 코드를 넣어서 페이로드 패턴을 좀 변형을 하는 목적의 모듈이다
->> 그리고 기타 보조 도구(= TOOLS)라는 플러그인(= PLUGINS)이 있다. msfconsole에서 불러와서 쓸 수 있으며 어떠한 부가 기능을 추가하거나, 아니면 일반적으로 msfconsole을 썼을때 1,2,3이라는 기능만 제공하고 있다면 플러그인을 이용해서 4라는 기능을 추가하거나, 3의 어떠한 동작 방식을 조금 변형해서 수행하는 역할을 한다. 이렇게 코드들을 작성해서 실시간으로 msfconsole을 사용을 하면서 모드에 새로운 플러그인을 추가하고 삭제하고를 할 수 있다
->> 다음으로 가장 중요한 부분은 "라이브러리" 부분이다. "Rex"가 제일 하위에 위치하고, "Framework Core" 그리고 "Framework Base"가 있다. 옆에 있는 그림은 클래스로 따지면 어떻게 상속을 하고 있는지를 보여주는 클래스 관계도이다. (원 그림상은 반대로 표현되어있다) 간단히 프레임워크 코어가 렉스에서 코드를 가져가서 쓴다는 개념으로 사용하면 된다. 렉스가 있고, 코어가 있고, 베이스가 있고, 그 위에 있는 모듈 ui 플러그인이 있다

-> 본격적으로 메타스플로잇 모드를 개발하려고 한다면 개발에 필요한 라이브러리 기능들이 어떤것이 있는지를 알아야한다. 물론 위의 그림에 보이는 항목 하나하나를 다 이해하면 좋겠지만, 굳이 보지 않아도 될 내용들도 많다
->> 우선 메타스플로잇 개발이라고 하면 크게 두 가지 관점을 볼 수 있다. 즉, 사용의 관점에서 개발은 두 가지로 볼 수 있다
->> 첫 번째는 모듈이다. (= 모듈 개발) 두 번째는 기능 개발이다. 메타스플로잇 자체가 모듈화 되어있다. 모듈화 되어있다는 것은 프레임워크라는 개념과 일맥상통하다. 프레임워크라는 것은 예를 들어서, 공간에 뼈대를 만들어놓고 공간 안에(뼈대 안에) 기능을 추가하고 삭제하기 쉽도록 밑단에서 어모듈화된 라이브러리를 제공 하는것이다. 그러한 관점에서 모듈 개발을 하려면 예를 들어, exploit 개발, auxiliary 개발을 말하는것으로 사실은 밑단의 내용을 크게 알 필요가 없다. 기존에 만들어진 모듈만 봐도 충분한 것이다. 하지만 좀 더 원리를 이해하고 보려면 한 코어 정도까지만 (프레임워크 코어 정도) 이해해도 충분하다. 기능 개발의 경우에는 "base"와 "core"와 "rex"를 모두 봐야하는데 베이스의 일부분과 코어의 일부분과 렉스의 일부분을 조금은 이해해야한다. 왜냐하면 기능 같은 경우에는 프레임워크의 밑단에서부터 그 위까지를 관통하는 역할을 하기 때문에 3개를 어느정도 다 알아야한다. 실질적으로 exploit 개발, auxiliary 개발 같은 경우에는 사실 코어만 잘 이해해도 개발하는데는 큰 지장은 없다
->> 제일 밑에 위치한 파란색이 "Rex"이고, 가운데 녹색이 "Core"이고, 제일 위에 있는 붉은색이 "Base"이다. 우선 "Rex" 보면 제공하는 기능들이 선언되어있는 내용들이 있다. 범용 클래스(= General Class)와 다양한 것들이 보인다. 여기서 확인해 볼 것은 "Rex"에는 있는데 "Core"에는 없는것들이 있다. 예를 들어서, 상수(= constants)는 "Rex"에도 선언되어 있고, "Core"에도 선언되어 있다. 반대로 "Protocol"은 "Rex"에는 있지만, "Core"에는 없다. 하지만 "Core"의 어디에 해당하는것인가를 찾아볼 수 있다. "Wrapper"나 "HTTP modules"에 올라간다고 볼 수 있다. 즉, "Rex"에서 선언된 기능과 "Core"에서 사용하는 기능들이 1대1 매칭이 되는게 아니라 코드들 안에서 (구역안에) 다양하게 가져와서 사용하는것이다. 그래서 마찬가지로 "Core"에서 선언된 기능들을 "Base"에서 또는 "Rex"에서 다양하게 가져와서 사용하는것이다

->> 우선 메타스플로잇 프레임워크의 근간을 이루는 핵심 코드는 "Rex"이다. "Rex"에서는 "General Class" 부분, "Core"에서는 "context & core" 부분(= 프레임워크를 어떻게 동작시킬지에 대한 부분), "General Class" 부분(= "Rex"의 범용 부분과 똑같은 개념인데 조금 더 코어에 사용하기 쉽게, 사용자에 가깝게 그리고 모듈 기능에 필요한 어떠한 예외들을 재정리했다. 예를 들어, 예외라는 것들을 한 100가지 구분했다면 코어에서 자주 쓰이는 혹은 코어에서 세분화하기 필요한 혹은 코어에서만 쓰이는 예외들을 한 10개로 정리했다거나 혹은 더 세분화해서 100가지를 500가지로 찢었다거나 하는 구현들이 담겨있다), "Base"에서의 "Sessions", "Simple Wrappers"는 코어에서 사용하는 기능들을 조금 더 사용하기 쉽게(= 가져다 쓰기 쉽게) 만들어놓은 것이다
->> 사실 msfconsole 인터페이스 코드를 한번 깊게 확인해보면 사용자 입장(모듈이나 기능을 개발하는 사용자 입장)에서 베이스가 크게 필요가 없다는 것이다. 베이스를 잘 몰라도 된다는 의미이다. 또한 사실 모듈 개발의 관점에서 렉스도 몰라도 된다
-> 그렇다면은 첫번째로 모듈 개발은 어떻게 할 것인가이다. 모듈 개발에서 사실상 필요한 부분은 "Core"의 "Modules" 부분만 확인하면 된다. "/lib/msf/core" 폴더에 들어가면 확인이 가능하다. 이 안에 구현된 코드들은 예를 들어서 익스플로잇이 동작하기 위한, 예를 들어서, 원격 익스플로잇이 tcp 연결을 하고, 그것으로 익스플로잇 데이터를 보내야 되고, 보낸 데이터를 세션 맺는다라고 한다면, 소켓 관련된 것을 "Rex"에서 가져다 쓸 것이고, "Protocol", 32비트/64비트 플랫폼을 공격한다면 "Arch"에서도 가져올 것이고, "Assembly"에서도 가져다 쓸 것이다. 이런 식으로 "Rex"를 몰라도 사용할 수 있도록 익스플로잇에 필요한 기능들을 선언이 되어있다. 그래서 이것이 결국은 믹스인이라는 형태로 제공되는 것이다. 즉, 모듈 개발할 때 아주 기본적인 루비 문법과 믹스인과 약간의 훔쳐보기(= 기존에 사람들이 만들어놓은 코드들을 한번 시간을 투자해서 보는것)만 조합되어도 사용자가 원하는 모듈 개발은 충분하다
->> 사실상 취약점을 찾고 그 취약점에 대한 익스플로잇을 만들 수 있는 사람이라면 이러한 모듈 기능 개발은 더 쉽다
->> 오히려 텍스트 에디터에서 익스플로잇을 짜는것보다 메타스플로잇에서 제공하는 프레임워크에서 제공하는 라이브러리를 사용해서 익스플로잇을 짜는게 사실상 더 쉽다. 그래서 이러한 모듈 개발은 이 정도만 해도 충분하다
-> 그리고 다음으로 기능 개발 관점은 인터페이스를 만든다거나, 새로운 기능을 추가한다거나, 여러가지들이 있다. 새로운 기능을 추가를 하려면 플러그인을 개발하면 되고, 인터페이스를 만들고 싶다면 하나의 새로운 인터페이스를 정의하면 된다. 그래서 기능 개발은 "Rex", "Core", "Base"를 다 이해해야 가능하다. 예를 들어서 인터페이스 개발하려고 한다면 msfconsole이라고 하는 콘솔 코드가 다 선언(정의)이 되어 있고, 그것을 다 이해를 해야한다. 예를 들어서 이벤트 처리는 어떻게 하고, 세션 관리는 어떻게 하며, 익스플로잇은 어떻게 실행을 하고 그 결과는 사용자에게 어떻게 출력해줘야 하는지 등등 복잡한 기능들이 유기적으로 얽혀있는것들이 직접 코드를 확인해서 구현이 그렇게 되어있구나를 이해해서 본인에게 필요한 기능들만 빼와서 나만의 인터페이스를 만드는것이다
->> 하지만 메타스플로잇 프레임워크에서는 "Simple Wrappers"라는 것을 제공한다. "Simple Wrappers"라는 것을 이용하면 이벤트 처리, 예를 들어서 익스플로잇 실행을 했을 때 결과가 안 나온다거나, 결과가 나왔다거나, 결과가 나왔으면 어떤 결과가 나왔고, 세션을 어떻게 맺으며, 이러한 복잡한 과정들을 몰라도 간단하게 인터페이스를 만들 수 있다
->> 인터페이스 기능을 구현한다는 것은 곧 내부 동작의 원리를 조금 더 깊게 이해한다라고 보면 된다. 왜냐하면 단순히 만들어놓은 기능을 쓰는게 아니라 본인이 메타스플로잇 개발자의 관점(사용자에게 필요한 기능을 제공하는 관점)이기 때문이다
->> "Serialization" 같은 경우에는 "Simple Wrappers"랑 같이 쓰는데, 예를 들어 "show options"를 하면 형식에 맞춰 테이블이 딱 보여지는것을 본적이 있을것이다. 이러한 것들을 출력해 줄 수 있게 해주는 것이라고 생각하면 된다

-> 일단은 우선적으로 "Rex"의 "General Class"와 "Core"의 "Framework context & core", "General Class"를 이해하고 본인이 만들고 싶은 기능들이 미리 어느정도 구현된 코드들을 한번 분석하면서 세 가지를 어떻게 가져다가 사용했는지를 이해하면 될 것이다
->> 팁으로 말하자면 라이브러리 코드를 보면 생각보다 주석이 잘 처리되어 있기 때문에 설명에 이해하기 편할 수 있다. 또한 코드가 체계화가 잘 되어있기 때문에 시간을 여유롭게 가지고 코드를 쭉 읽어본다면 이러한 구성 요소로 이루어져 있고, 이 구성 요소들이 윗단에서 어떻게 사용되고, 사용자에게 어떻게 보여지는지를 모두 이해할 수 있을것이다

* MSF 모듈 이해
: 이번에는 메타스플로잇의 모듈에 대해서 알아본다

->> 여기서 주의할 점은 모듈은 루비 언어의 모듈이 아니라는 것이다. 여기서 말하는 모듈은 "exploit", "auxiliary", "payload", "post", "encoder", "nop"를 말하는 것이다
->> 3번째 줄에서 말하는 모듈이 프레임워크에 로드 되면 클래스의 복사본이..."을 설명하면 프레임워크라는 것은 하나의 어떠한 상태 정보라고 보면 된다. 프레임워크라는 것을 로드하면 프레임워크 상태 정보를 담고 있고, 그 하위에 특정 모델에 대한 정보가 붙고, 세션이 붙고, 이벤트, 이벤트 디스패처?가 붙는 방식이다. 예를 들어, "framework"라는 키워드로 프레임워크의 현재 상태에 접근할 수도 있고, "framework.datastore", "framework.module" 등 이러한 접근자로 현재 모듈의 정보라든지, 모듈의 이름이라든가, 파일 경로라든가. 이런것들을 모두 확인할 수 있다. 이것은 "irb" 대화형 모드에서 확인이 가능하다

-> 다음으로 모듈의 공통 요소 중 옵션을 확인해본다

->> 옵션은 msfconsole을 실행했을때 "show options" 명령어로 보는 옵션 확인을 말한다. 여기서 "class Metasploit"에서 클래스는 언어적인 클래스 개념이라기보다는 그냥 모듈 하나라고 생각하면 된다
->> 모듈 옵션 같은 경우에는 모든 모듈이 가져야 할 기본 옵션 목록이 존재한다. 그래서 항목은 만들어져 있고, 항목의 내용은 비워져 있거나, 무의미한 쓰레기 값들이 들어있다. 그래서 상속을 받게 되면 자동적으로 여기 선언된 기본 옵션들이 현재 모듈로 들어오는것이다. "super"라는 메소드로 기본 옵션들을 가져오고, "(update_info())"라는 메소드를 실행해서 내용을 채우거나, 추가 항목들을 등록해준다. 그래서 모든 모듈의 가장 처음에는 옵션을 설정하는 부분이 들어가있다. 단순한 옵션으로 동작하는게 아니다. 예를 들어서, 익스플로잇의 페이로드 같은 경우에는 밑에서는 페이로드라는 접근자로 어떠한 메소드를 단순하게 실행시키지만 위에서 설정해 둔 옵션을 참고해서, 즉, 옵션 값을 토대로 메소드가 실행되는 원리를 가지고 있다. 별거 아닌 옵션인것 같지만 어떻게 설정하느냐에 따라서 코드의 구성도 달라질 수도 있다는 것이다. 코드 안에서 사용하는 어떠한 메소드들의 내부적인 기능도, 역할도 달라질 수 있다는것이다
->> 옵션 유형에서 보이는 "AdvancedOptions"와 "DefaultOptions"가 있는데 "DefaultOptions"은 "show options" 명령을 하면 나오는 옵션 값이고, "AdvancedOptions"는 "show Advanced" 명령을 하면 나오는 옵션 값이다. 사실 모듈이 돌아가는데 "AdvancedOptions"은 필요 없고 특정 모델에서 추가 옵션으로 지정을 해놓은 경우에 사용하는 것이다
->> "datastore"는 "irb" 모드에서 확인 가능하다
->> "share_database"는 예를 들어서, msfconsole에서 "use" 해서 익스플로잇 모듈을 하나 불러온다. 그 다음에 "show options"해서 옵션 설정에 들어가면 익스플로잇에 관련된 옵션에 필요한 정보들이 뜨는데, 무엇을 설정해야 되는지를 확인한다. 여기서 "set payload"를 치지 않는한 "payload" 옵션이 보이지 않는다. 그럼에도 불구하고 여기있는 옵션만 모두 지정을 한다면 알아서 msfconsole 내부적으로 페이로드 인스턴스를 만들고, 페이로드 옵션을 설정한 다음에 익스플로잇을 실행해준다. 그것을 가능하게 해주는것이 "share_database"이다. 나중에 인터페이스를 만들때 익스플로잇 모듈에도 옵션이 필요하고, 페이로드 모듈에도 옵션이 필요하다. 하지만 사실 익스플로잇 모듈에서 설정한 옵션 정보를 토대로 페이로드 옵션을 설정할 수 있다는 것이다. 즉, 익스플로잇 모듈이 옵션을 설정한 다음에 익스플로잇 모듈에 share_database 명령을 넘겨주고, 페이로드에 넘겨주면 페이로드에서 필요한 옵션들이 자동으로 설정된다

-> 모듈의 기본 옵션에는 이러한 것들이 있다

->> 위의 그림에서 보듯이 비워져 있거나, 의미없는 내용이 들어가 있는데 실제 코드를 보면 "super(update_info())" 부분에 모듈의 이름을 적고, 설명을 적힌 것을 확인할 수 있을것이다
->> "모듈 유형 및 기능별로 기본적으로 사용하는 옵션의 종류가 다름"은 위의 "기본 옵션(코드 상의)"에 있는 내용이 달라지는게 아니라, 예를 들어 TCP 통신을 사용하는 모듈인 경우, Remote 익스플로잇인 경우 등 상황에 필요한 기능들이 있는데 필 수 기능들이 이러한 코드마다 다르다라는 것을 알고 있다면 임의로 지정을 하거나, 믹스인 차원에서 로드가 가능하다

-> 그래서 믹스인 기능이 아주 중요하다

->> "모듈 유형 및 기능에 맞는 믹스인을 사용할 줄만 알아도 모듈 개발이 아주 쉬워 짐"을 보듯이 믹스인만 알면 끝이다. 그렇다고 믹스인이 어떻게 구현되는지는 알 필요가 없다. 단지 믹스인에서 제공하는 기능을 잘 가져와서 쓰기만 하면 된다. 실제 코드를 보면 처음에 "require"라고 해서 msf 코어와 렉스를 사용하겠다고 선언해놓은 것을 볼 수 있다. 루비 언어를 연습할 때 본 것처럼 렉스와 msf core가 필요하다고 선언만 해놓은 것이고, 세부적으로 msf3 해서 클래스를 설정하고, 클래스 안에서 include를 한다.(= 믹스인을 인클루드한다) 결국 "이것이 필요하다"라는 것만 선언해주고 실질적인 코드 안에서 include로 믹스인을 가져오는데, 여기서 본인이 필요한 기능을 불러오는것이다. 이렇게 선언하게 되면 루비 연습 때와 같이 모듈에서 제공하는 모든 메소드를 클래스 instance처럼 사용할 수 있는것이다. 즉, 클래스 내부에서 사용할 수 있는것이다. 그래서 코드(= msf3) 앞에다가 클래스라고 선언을 하는것이다
->> 그리고 믹스인을 추가하면 기능 제공뿐만 아니라 기본 옵션이 변경된다. 예를 들어서 원래 기본 모듈 경우에 위에서 봤던 "Name, Description, Version, ..." 것만 있다면 http server 관련된 믹스인을 추가하게 되면, 서버가 돌아가기 위한 옵션들이 있을것이다. "SRVPort", "Uripath" 등의 옵션들이 있다. 이러한 옵션들을 믹스인 자체적으로 기본 옵션에 등록을 해준다. 그래서 믹스인을 잘 써야하며, 특정 믹스인을 로드했을때 어떤 옵션이 제공되는지도 알고 있어야한다
->>> TCP 통신을 하려면? 원래라면 소켓 구조체를 생성하고, 필요한 정보를 넣어주고, 구조체에다가 클라이언트 서버 연결 정보를 입히고, 그 다음으로 데이터 통신을 성립하고, 예외를 잡아주고 등등 복잡한 과정이 필요하지만, 그럴 필요없이 "connect > put > disconnect" 명령만 해주면 그러한 연결 관리를 모두 해준다. 데이터 보내주고, 연결 끊고 등을 이런식으로 간단하게 TCP 통신 코드를 구현할 수 있는것이다
->> 여기서 믹스인이 어떠한 기능을 제공하는지 확인하는 방법은 크게 3가지가 있다. "믹스인 코드를 따라가 본다." 코드 실습에서 했듯이 "Msf::Exploit::Remote..."라고 되어 있는게 결국은 디렉토리 계층 구조를 따라간다고 말했을 것이다. 그래서 라이브러리 디렉토리 하위에 있는 믹스인에 해당하는 경로를 찾아 들어가서 그 코드 안에서 제공하는 메소드를 읽어보면 나중에 개발할때 원하는 기능을 알수 있다. 이와 같은 방법은 조금 무식한 방법이다. 가장 좋은것은 기존에 만들어놨던 코드를 먼저 보는것이다. 개발하기 전에 코드를 먼저 분석해보고 어떠한 기능을 가지고 있는 코드는 어떠한 믹스인을 가져와서 쓰는구나를 알아가면 된다. 그리고 모델 디버깅을 해보는 방법이 있다. 근본적으로는 첫번째 방법과 두번째 방법이 같지만, 첫번째 방법은 직접 디렉토리 경로로 들어가서 코드를 보는것이라면, 두번째 방법은 디버거 상에서 특정 믹스인에서 어떠한 소스가 포함되어 있는지, 그 소스에서 어떤 기능을 쓰고 있는지를 직접 확인하는 것이다. 자세한 설명은 디버거를 사용할 때 알아볼 것이다. 마지막으로 "API 래퍼런스"는 "https://rapid7.github.io/metasploit-framework/api/" 사이트가 있다.

->> [Search]에서 원하는 믹스인을 검색하면 된다. 예를 들어, "Exploit::EXE"를 검색해보면

->> 확인 결과, 어떠한 것을 포함하고 있는지, 코드는 어디에 정의되어 있는지, 제공하는 메소드는 어떤것들이 있는지를 설명하고 있는것을 확인할 수 있다. 현재 보고 있는 사이트의 내용들도 결국 코드에서 자동 생성된 문서이기 때문에 코드를 보시는게 가장 정확하지만, 조금 번거러울 뿐이다

-> 이제는 각각의 모듈이 어떻게 구성되어 있는지 구조를 알아본다

->> 가장 먼저 익스플로잇 모듈은 시스템에 존재하는 취약점을 이용해 제어권을 획득하는 공격 코드이다. 그래서 2번째 줄과 같이 선언이 되어있다. 항상 익스플로잇 모듈을 보면 "require msf/core, Rex"를 가져오고, 그 다음에 "class Metasploit < Remote 또는 Local"이 있고, 그 다음으로 "include" 부분, 다음으로 옵션 설정, 그리고 4~8번째 줄의 내용의 코드들이 있다
->>> 여기서 말하는 "취약점 관련 코드 부분"은 트리거를 할 수 있는것으로, 예를 들어, "buf"에다가 취약점 트리거 할 수 있는 일련의 값들을 넣어서 buf를 전달하는 방법이 있다. 그리고 데이터 저장소에 미리 만들어놓은 익스플로잇 파일을 가져와서 사용하는 방법도 있다. 예를 들어서, Flash 취약점의 경우 "CVE-...."를 지정해주고, 이미 데이터 저장소에 있는 ".swf" 파일을 가져와서 클라이언트로 보내주는 식으로 코드가 구성되어 있을수 있다. "메모리 보호 기법 우회 부분"의 경우에도 관련된 믹스인이 필요하다. "rop", "egghunter", "seh" 등 믹스인에서 제공하는 메소드를 통해서 수행이 가능하다. "페이로드 생성 및 인코딩 수행 부분"의 경우에는 "payload.encoded"라는 지시자를 많이 쓴다. 여기서 "payload"가 메소드이고, "encoded"가 접근자이다. "p = payload"라고 하면 자동으로 페이로드가 생성된다. 이것은 페이로드 옵션에서 지정한 내용을 토대로 페이로드를 생성하는데 그냥 쓰는것이 아니라 ".encoded"라는 접근자를 쓰면 인코딩 된 페이로드 정보를 저장할 수 있다
->>> 가끔 메모리 보호 기법 우회가 필요 없는 경우도 있다
->> "코드 전달"은 예를 들어, http를 쓰면 uri 형식으로 요청을 하거나, 요청에 대한 코드를 주거나 할 수 있고, TCP로 전달 할 수 있고, 혹은 파일 폼 취약점이라면 "file_create"로 파일을 그냥 (로컬 디텍토리에다가) 떨어뜨려줄 수 있다
->> 마지막으로 "check"라는 메소드가 있는데 4~7번째 줄까지는 필수이고, 8번째 줄은 선택 사항이다. 엄밀히 말하면 권장 사항이다. "check" 코드는 익스플로잇을 수행하려는 대상 시스템에 익스플로잇을 보내지 않고 (혹은 보내기 전에) 시스템이 취약한지의 여부를 판단하는 코드이다. 그래서 개발자 사이트에 들어가면 가능한 check 메소드를 만들것을 권장한다. 예를 들어서 특정 취약점이 패치하기 전에 "a"를 보내면 "1 2 3 4"라고 응답을 했는데, 패치한 후에는 "a"를 보내면 "b"라고 응답이 오는 차이점을 이용해서 익스플로잇을 보내지 않고도 취약점 여부를 판단할 수 있다. 혹은 배너 정보를 긁어와서 취약한 버전이다라고 판단해서 취약점이 있다, 없다, 또는 있을것 같다라고 판단해주는 것이다

-> 다음으로 보조 도구를 알아본다

->> "auxiliary"가 보조 도구라고 알고 있으면 된다. 이것 또한 구조는 동일하다
->> "auxiliary" 특화 코드는 주로 연결과 전송과 해제 하는 기능들과 데이터 저장소 관련된 기능 데이터와 데이터 스토어 관련 기능들이 있다. 이것은 우리가 스캐너를 해서 공격 대상 시스템을 확보한 결과를 DB에 자동으로 저장하는 기능들이 있다. 그래서 데이터 스토어 관련된 기능과 통신 관련된 기능들이 많이 있다는 것을 알고 있으면 된다. auxiliary 모듈의 핵심은 어떠한 데이터를 주고받을 것인가이다. 그래서 마찬가지로 auxiliary은 특히 믹스인을 잘 알면 좀 더 작성하기가 쉽다
->>> 사실 exploit 같은 경우에는 메타스플로잇을 잘한다고 되는게 아니라 exploit development 잘해야지만 되는것이다. auxiliary는 exploit development와 같이 어려운 내용을 알 필요는 없다. 그저 믹스인만 잘 활용해도 된다(정보 수집 관련된 코드가 많기 때문에)
->> 2014년도 부터 "LoginScanner"에 관한 기능의 집약체가 만들어졌다. 어떠한 형식이라고 보면 된다. 즉, 스캐너를 작성할때는 "LoginScanner"라는 형식을 따라줘야한다. 나중에 실습에서 해볼 것이다

->> 포스트 모듈은 후속 공격을 하는 것이다. 익스플로잇이 성공한 다음에 하는 공격을 말한다. post module은 msfconsole에서 바로 로드해서 쓸 수 있는게 아니라 익스플로잇이 성공한 다음에 세션이 맺어지면 그 세션 정보를 넘겨서 실행을 해야된다

-> 마지막으로 페이로드, 인코더, nop를 알아본다

->> 코드를 보면 구성은 동일하다. 페이로드는 주로 옵션값으로 모든것을 설정한다
->> 사실 이 세가지는 모듈보다는 모듈이 존재할 수 있게 해주는 라이브러리 코드를 보는게 더 중요하다. 즉, 페이로드의 라이브러리 코드, 인코딩의 라이브러리 코드, nop의 라이브러리 코드를 보는게 더 중요하다

* 실습#2 - MSF 디버깅 환경 구축
: 이번에는 메타스플로잇 프레임워크 디버깅 환경 구축에 대해서 알아본다

-> 사실 디버깅이라고 하기는 애매하다. 왜냐하면 디버깅을 가능하게 해주는 "Pry"와 "Pry-debugger" 두가지가 있다. 현재 메타스플로잇 2.대 버전을 사용하고 있는데 여기서는 "Pry-debugger"가 설치가 잘 되지 않는다. 아직까지는 해결 방법이 없는듯 하다. 그래서 "Pry"만 사용해보면 된다
-> "Pry"는 여러 편리한 기능을 제공하는 대화형 해석기(= irb)이다. irb는 현재 문맥을 들어갔을때 지금 어떠한 특정 문맥을 포착한 상태에서 irb 실행 하면 상태 정보를 볼 수 있는 기능을 제공한다. 인스턴스 값을 본다거나, 저장소에 저장된 값을 본다거나. 메타스플로잇에서 irb에 접근할 수 있는 방법은 두 가지 밖에 없다. 하나는 msfconsole 상에서 접근하는 방법, 또 다른 하나는 meterpreter session 상에서 접근을 하는 것이다. 메터프리터 세션 상에서 접근을 하면 좀 더 많은 정보를 얻을 수 있다. 그래서 메터프리터 스크립팅을 할 때 irb 모드를 많이 사용하기도 한다. 하지만 디버깅의 관점에서 (모듈을 개발하는 입장에서) 개발 중인 모드를 중간에서 잡아서, 코드 중간에서 브레이크 포인트를 걸어서 상태 정보를 확인한다던가, 인스턴스 값이 어떻게 되는지, 변수에는 어떤 값이 있는지는 메터프리터에서는 확인할 수 없다. "Pry"를 사용하면 그러한 원하는 부분을 포착해서 원하는 코드를 확인할 수 있다. 여기서 아까 말했던 "Pry-debugger"라는 것을 사용하면 Debug-GDB처럼 next, breakpoint 등을 할 수 있는데, 사실 없다고 모듈 개발하는데 큰 지장은 없다

-> 칼리리눅스에 "Pry"를 설치해본다. (설치전 주의할 점은 네트워크를 연결해주고 시작해야한다 = NAT)
->> "cd /usr/share/metasploit-framework/" - Enter
->> "gem install pry pry-doc" - Enter

->> "ls" - Enter (= gem 파일 확인)
->> "vi Gemfile" - Enter
->> "gem 'pry'" - ESC - ":wq" - Enter

->> "bundle install" - Enter

->>> 어떠한 원리인지 크게 몰라도 된다. 간단하게 루비에다가 "Pry" 관련된 내용을 추가해놓고, 메타스플로잇에서 사용하는 루비에다가 "Pry"를 설치해준것이다

-> 설치가 끝났으니 사용을 해본다. 사용법은 생각보다 간단하다
->> "cd modules/exploits/windows/ftp/" - Enter
->> "vi freeftpd_pass.rb" - Enter

->> "require 'pry'" - Enter (= require가 있는 다음 줄에 추가해준다)
->> "binding.pry" - ESC - ":w!" - Enter (= 익스플로잇 하는 순간을 포착해서 정보를 조회하는 옵션을 추가했다)

->> "msfconsole" - Enter

->> "use exploit/windows/ftp/freeftpd_pass" - Enter
->> "show options" - Enter
->> "set rhosts 1.1.1.1" - Enter (= 공격을 하는것이 아니기 때문에 아무 주소나 입력해준다)

->> "exploit" - Enter

->>> 확인 결과, "binding.pry" 장소를 포착한것을 볼 수 있다. 여기서부터 여러가지를 조회할 수 있는것이다. 아까 잠깐 설명했던 "Pry-debugger"까지 설치하게 되면 조회뿐만 아니라 디버깅 툴에서 사용하는 "step" 명령어를 이용해서 코드를 실행할 수도 있다. 현재는 "Pry"만 설치가 되어있기 때문에 "step, next, breakpoint"는 사용할 수 없다. 하지만 이 상태만으로도 충분히 많은 정보를 조회할 수 있기 때문에 유용하다
->> "whereami" - Enter (= 명령어들을 진행시키다가 현재 어디에 위치해 있는지를 확인할 수 있다)

->> "help" - Enter (= 여러가지 명령어들을 확인할 수 있다)

->> "q" (= 특정 명령어를 실행하고 "END"라는 명령어가 떴을때 탈출하는 방법)

"q"를 눌러주면 대화형 세션으로 돌아오게 됨

->>> 유용한 명령 몇 가지만을 테스트해본다
->> "framework" - Enter

->>> "framework"라는 접근자는 현재 프레임워크에 세션, 연계 jobs, 연계 플러그인이 실행되고 있는게 없는것을 볼 수 있다. 작업을 등록하지 않았기 때문에 없는것이다
->> "datastore" - Enter

->>> 데이터 스토어 접근자를 치게 되면 현재 옵션에 설정한 내용들을 모두 확인할 수 있다. 기본 옵션뿐만 아니라 advanced 옵션까지도 확인이 된다
->> "q" (= 탈출)

->> "datastore["RHOST"]" - Enter

->>> 지정한 "rhost" 값을 확인할 수 있다. 더불어 "rhost" 값을 바꿀 수도 있다
->> "datastore["RHOST"] = '2.2.2.2'" - Enter

->>> 여기서 핵심은 접근 가능한 접근자나 어떠한 구조체 이름, 메소드 이름을 안다면 메타스플로잇 인터널에서 제공하는 메소드나 접근자를 안다면 모듈이 실행된 상태에서 정보에 접근하거나, 정보를 수정할 수 있다는 것이다
->>> 다음으로 예를 들어서 소스 코드에 선언한 메소드가 기억이 안난다면 "show-soruce <메소드명>"을 쳐주면 된다
->> "show-source initialize" - Enter

->> "q"

->>> 다음으로 더 강력한 기능이 존재한다. 예를 들어서, 믹스인이 어떤것을 제공하는지 모르겠다고 했을때 믹스인을 찾아본다
->> "show-source Msf::Exploit::Remote::Ftp" - Enter

->>> 소스를 보면 믹스인이 어디에 위치하는지, 모듈 이름이 무엇인지에 대한 믹스인 코드를 확인할 수 있다
->> "q"
->> "ls" - Enter

->>> "ls"는 소스 코드에서 가져오는 모든 모듈과 메소드 이름, 접근자를 확인할 수 있다. 이 중 예를 들어서, "arch"를 확인해본다
->> "show-source Msf::Module::Arch#arch" - Enter ("::" 찍은것은 메소드이고, "#"은 접근자이다)

->>> 여기서 "arch"는 접근자이며, 특정 기능을 수행하는 메소드라기 보다는 특정 기능을 수행한 뒤에, 결과 혹은 현재 모듈 코드에서 선언해놓은 아키텍처에 대한 정보를 담고 있는 접근자이다
->> "arch" - Enter

->>> "arch"는 현재 사용 중인 아키텍처의 정보를 확인할 수 있다

-> 일단은 "Pry"로 이용하는 부분은 여기서 마무리를 한다. 사실 "next, step, breakpoint"와 같은 디버깅 기능이 없는데 무엇을 쓰냐라고 반문할 수 있다. 하지만 상당히 유용하게 쓰이며, 특히나 모듈 개발할 때 유용하게 쓰인다
-> 다음에는 모듈 분석과 인터페이스 개발할 때 디버거를 많이 사용할 것이다. 그렇기 때문에 반드시 실습 과정을 거쳐서 여기에 나온 명령들을 한번씩은 쳐보는것이 좋다. "help"에서 검색된 여러가지 것들을 테스트해보는게 좋다
-> 마지막으로 본인은 실시간으로 디버깅을 해야겠다는 사람들은 "byebug"라는 도구를 설치하면 된다

* 실습#3 MSF 모듈 분석
: 이번에는 메타스플로잇 모듈을 직접 분석해본다

-> 여기서 모듈을 분석하는 이유는 모듈 자체 분석을 통해서 버그를 찾자는 취지가 아니라 기존에 만들어진 것을 통해서 어떻게 모듈을 개발할지의 가이드를 얻기 위해서이다. 예를 들어 프로그래밍도 마찬가지로 혼자 삽집을 해도 잘 만들어진 코드를 보고 연습해야 좀 더 본인의 한계를 넘어설 수 있는 과정과 같다고 보면 된다. 메타스플로잇 모듈의 잘 만들어진 코드를 보다 보면 오히려 일반 프로그램보다 더 쉽게 느껴질 것이다. 왜냐하면 모듈에 대한 설명도 잘되어 있고, 모듈이 어떤 기능을 하는지 보고, 기능 구현을 어떻게 했는지를 대략 100개 정도만 봐도 대충의 그림이 그려진다. (다소 무식한 방법이기 때문에 권장하지는 않는다)
-> 크게 분류해보면 "exploit", "auxiliary", "post"가 한 가지 유형이고, "encoder", "payload", "nop"가 또 다른 유형이다
-> 이번에는 "Pry"를 활용하지 않고 코드를 읽어내려가는 방법을 설명할 것이다. (만약 좀 더 자세히 궁금하다면? 메소드가 있는데 코드상으로 이렇게 돌아가는지는 알겠지만, 실질적으로 어떤 내용이 클라이언트에 전달되는지 모르겠는 사람은 익스플로잇 하기 직전에 "binding.pry"를 걸어놓고 만들어진 데이터 버퍼가 어떻게 구성되는지, 코드상이 아니라 만들어진 버퍼 내용을 저장 공간을 직접 들여다보고 실시간으로 수정해보면 된다)

: 본격적으로 분석을 시작해본다
-> 메타스플로잇 모듈 실습에서 이용했던 freeftpd_pass 취약점을 이용해본다
->> "cd /usr/share/metasploit-framework/modules/exploits/windows/ftp/" - Enter
->> "vi freeftpd_pass.rb" - Enter

vim colorscheme 설정하지 않음
vi의 색깔과 줄 번호를 쓰고 싶다면 google에 "kali vim colorscheme" 을 검색해서 설정하면 됨

->>> 본격적으로 분석을 시작해본다. 우선 익스플로잇 코드에는 "require"가 있고, 클래스 시작 부분이 있고, 그리고 "include" 부분이 있고, "initialize" 부분이 있고, 옵션 부분이 보인다. "require msf/core" 코드를 보면 "Rex"는 가져다 쓰지 않는것을 볼 수 있다. 그렇다고 해서 Rex 코드를 쓰지 않는것은 아니다. 라이브러리 계층 구조를 보면 msf core도 rex를 기반으로 만들어진 라이브러리이기 때문에 굳이 
"require msf/rex"를 하지 않아도 된다. 이렇게만 해주어도 모듈 코드는 필요한 것들을 모두 로드가 된다고 보면 된다
->>> 그리고 클래스를 사용하는 이유는 기본적으로 만들어진 틀(= "Msf::Exploit::Remote")이 보이는데, "Msf::Exploit::Remote"은 "msf/modules"에서 상속 받는다는것을 알고 있을것이다. 처음부터 토대를 쌓는것이 아니라 기본적으로 만들어진 토대 위에다가 현재 사용할 모드를 올리겠다는 것이다. ("Rank = ..."은 뒤에서 설명 할 것이다)
->>> 그리고 믹스인이 보인다. 믹스인에서 어떤 메소드를 제공하는지를 확인하는 방법은 "Pry" 설명에서 설명했다. 사실 믹스인 코드(= "include Msf::Exploit::Remote::Ftp") 가 핵심이다. 믹스인만 잘 보아도 대충 이것이 어떤 익스플로잇이라는 것이 추측이 가능하다. 당연히 예시에 나오는 것은 "FTP" 관련 익스플로잇 일 것이다

->>> 그리고 "initialize"는 클래스가 로드될 때(= 사용될 때) 자동으로 초기화되는 부분이다. 이론 부분에서 설명했듯이 "super"라는 것을 통해서 기본적으로 모듈 옵션의 뼈대를 가져온 다음에 내용을 입힌다. 여기서 주목해야 할 부분의 코드는 "Payload, Platfrom, Arch, Targets"이다. 이 4가지는 익스플로잇에 특화된 옵션이다. 예를 들어서 "BadChars" 같은 경우에는 페이로드에 들어가서는 안될 문자를 의미한다

->>> 이렇게 옵션을 지정해주면 나중에 페이로드 생성은 "bof = payload.encoded" 한 줄이 전부이게 된다. 즉, 저러한 옵션을 참고해서 이 한 줄로 페이로드를 생성하는 것이다. 그렇기 때문에 옵션이 상당히 중요한 비중을 차지한다

->>> 다음으로 보이는 "register_options"는 기본 옵션을 추가하거나, 해제할 수 있는 코드이다. 위에 "initialize" 부분의 옵션들은 모듈에 관한 기본 옵션이고, 그 위에서 "include"에서 말했듯이 믹스인을 추가하면 옵션이 자동으로 바뀐다고 설명했다. 그러한 믹스인을 찾아가보면 믹스인이 로드될 때 자동으로 등록되는 기본 옵션이 있다. 위의 코드의 의미는 그것 외에도 기본으로 register 하겠다는것이고, 기본으로 "FTPPASS"라는 것을 없애겠다는 의미이다. 즉, 기본으로 제공되는 옵션 이외에도 새로운 옵션을 추가하거나, 삭제하는것도 가능하다는 것을 알고 있으면 된다

->>> 다음으로 보이는 "def check" 메소드는 권장 사항으로서 현재 코드에서 취약점을 "banner"를 이용해서 찾는것을 볼 수 있다. 배너를 연결했다가, 연결을 끊은 다음에 배너를 확인해서, 배너가 "/freeFTPd 1\.0/" 일 경우에는 취약점이 있는것으로 보고, 그렇지 않으면 안전한 것으로 판단한다. 사실 권장 사항이라서 "check" 메소드가 있는것도 있고, 없는것도 있다

->>> 다음으로 보이는 "exploit" 메소드에서는 메모리 보호 기법을 따로 사용하지 않는것을 볼 수 있다. "seh, rop, egghunter"가 보이지 않고, "bof"에다가 넣고 보내면 익스플로잇이 되는것으로 확인된다. 버퍼를 만드는 부분(= "bof = payload.encoded")에 페이로드를 넣고, 취약점을 트리거 하는 부분(= "raw_send("PASS #{bof}\r\n")")에서 보듯이 "PASS"라는 옵션 뒤에 만든 버퍼를 넣어주면 되는것 같다
->>> 코드만을 보고 이해할 수도 있지만, 추가적으로 "binding.pry"를 걸어서 문맥을 잡은 상태에서 보낼 데이터가 어떻게 구성되어 있는지를 확인하거나, 수정하거나 등등이 가능하다는 것을 알고 있으면 좋다

-> 정리를 해보면 익스플로잇 코드를 볼 때, "require"가 무엇을 가져오는지, (class 코드 부분에서) "Remote"인지, "Local"인지와 (include 코드 부분에서) 믹스인은 어떤것을 가져오는지와 (initialize 코드 부분에서) 특이한 옵션들을 설정하고 있는지 또는 다른 모듈에서 흔히 볼 수 있는 옵션을 설정하고 있는지와 흔히 볼 수 있는 옵션에서도 "BadChars"는 어떻게 다르게 사용하고 있는지를 확인해보면 된다
->>> 매번 개발의 측면에서 강조하지만, 익스플로잇을 분석하고 개발한다는 관점 자체에서 메타스플로잇이 중요한것이 아니다. exploit-development라는 이론을 이해하는게 더 중요하다. 왜냐하면 "Ret"를 모르고 "Offset"이 왜 필요한지 모르고 "BadChars"가 뭔지를 모르면 사실 개발이 의미가 없기 때문이다

: 다음으로 추가적으로 auxiliary를 분석해본다 (= 이전에는 exploit에 있던 ftp 코드이고, 이번에는 auxiliary에 있는 ftp 코드이다)
->> "cd /usr/share/metasploit-framework/modules/auxiliary/dos/windows/ftp/" - Enter
->> "vi winftp230_nlst.rb" - Enter

->>> 여기서 주목해야 할 부분은 믹스인이다. "include Msf::Exploit::Remote::Ftp"는 ftp 연결을 요청을 하고, 데이터를 보내고, 연결을 끊기 위해서 익스플로잇에서 선언되어 있는 ftp 믹스인을 가져온 것이고, "include Msf::Auxiliary::Dos"는 Dos 모드의 공격의 관점을 구현하기 위해서 Auxiliary의 Dos를 가져온 것이다. 그리고 "class" 줄에서 보듯이 auxiliary에서 상속을 받는다는 것을 볼 수 있다

->>> 다음으로 보이는 "initialize" 메소드에서 보듯이 모듈 클래스에서 제공하는 기본 옵션만을 사용하는 것을 볼 수 있다. 따로 추가 옵션을 등록하지 않는다
->>> 그리고 코드 또한 매우 단순하다. 왜냐하면 페이로드가 필요하지 않기 때문이다. 익스플로잇은 "raw_send("NLST #{'..?' * 35000}\r\n")"이다. 익스플로잇만 있고, 그 뒤에서 무엇을 할지는 정해질 필요가 없다. 설령 믹스인에 익스플로잇 믹스인을 사용한다고 하더라도 필요치 않다는 것이다

: 다음으로 추가적으로 "scanner"를 분석해본다
->> "cd /usr/share/metasploit-framework/modules/auxiliary/scanner/ftp/" - Enter
->> "ls" - Enter
->> "vi ftp_version.rb" - Enter (= 버전을 확인하는 코드)

->>> 코드는 위에서 설명한 것과 똑같은 방식으로 분석하면 된다

-> 다음으로 페이로드, 인코더, nop 같은 경우에는 옵션만으로 코드를 다 처리하는 경우가 대부분이다. 옵션단에서 페이로드 코드를 하드 코딩하는 경우도 있다. 옵션에서 렉스 라이브러리 혹은 코어 라이브러리에서 하드 코딩된 코드를 미리 선언해 놓았으면 그것을 가져오는 기능만 하는 옵션이 지정되어 있는 식으로 구성되어 있는것이다
->>> 페이로드, 인코더, nop 부분은 포스트, 익스플로잇, 억시리얼리를 보조하는 부분이기 때문에 크게 보지 않아도 괜찮다. 기본적으로 사용하는 모듈의 입장에서는 구현되어 있는것을 가져다 쓰면 되는것이지, 특별한 일이 없다면 페이로드, 인코더, nop를 제작하는 일은 없을것이다. 결국 주로 익스플로잇 모듈을 많이 작성할것이며, 그에 중점적으로 설명을 이어나갈 생각이다