Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
MemITM — 메모리 내 중간자 공격을 수행하는 도구 | Kitploit
도구/GitHubGitHub/amossys/memitm
Dynamic Analysis (Sandboxing)Memory ForensicsExploitationReverse EngineeringDebuggersFuzzingBinary Analysis
GitHubamossys/memitm

MemITM

메모리 내 중간자 공격을 수행하는 도구

저장소 보기
126277년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

MemITM 도구란 무엇인가?

MemITM(Mem In The Middle) 도구는 Windows 프로세스 메모리에서 "메시지"를 쉽게 가로채기 위해 개발되었습니다. 네트워크 메시지를 암호화 전에 캡처하거나 IPC 메시지를 캡처하고, 이를 검사하거나 퍼징을 위해 변경하기 위해 많은 맞춤형 메모리 가로채기 도구를 개발했습니다. 각 도구는 매우 맞춤형이었고, 일반적이지 않았으며, C/ASM으로 구현되어 사용/유지보수/적응이 쉽지 않았습니다.

MemITM 도구는 이러한 문제를 해결하기 위해 개발되었으며, 다음으로 구성됩니다:

  • 가로채기 지점을 어디에 어떻게 배치해야 하는지(상대 주소, 버퍼와 그 크기를 찾는 방법, 훅을 배치하는 방법 등)를 나타내는 "config" 파일을 생성하는 IDA Python 스크립트;
  • 대상 프로세스에 주입되어 config를 로드하고 훅을 배치할 DLL 파일;
  • 대상 프로세스에 DLL을 로드할 DLL 파일 인젝터;
  • 주입된 DLL/훅과 통신하고 실시간으로 가로채진 버퍼를 가져오며(변경 가능) 사용자가 원하는 대로 수정할 수 있는 매우 간단한 콜백을 제공하는 Python 스크립트.

여기서 다운로드할 수 있습니다(소스 + 컴파일됨): https://github.com/Amossys/MemITM

MemITM은 얼마나 간단한가? (예제1: WriteFile)

특정 Windows 프로세스에서 파일 쓰기를 가로채고 싶다고 가정해 봅시다(더 간단한 방법이 있지만 예제를 위한 것입니다). 파일 쓰기는 kernelbase.dll에서 내보내는 WriteFile 함수에 의해 수행되며, BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, ...) 형식을 따릅니다. WriteFile은 __fastcall 함수입니다. lpBuffer는 RDX가 가리키고 NumberOfBytesToWrite는 R8이 가리킵니다. 이 버퍼들을 가로채 봅시다.

  1. IDA Pro에서 "kernelbase.dll" 파일을 열고, generate.idapython.py 스크립트를 로드한 후, getHook(LocByName("WriteFile"), "rdx","r8")을 실행한 다음 updateConfig("config.bin")을 실행합니다.

  2. notepad를 실행한 후, python memitm.py notepad.exe config.bin을 실행합니다.

이것으로 끝입니다! WriteFile 함수에 훅이 배치되었고, memitm.py의 "로거" 및 "퍼저" 함수가 버퍼의 복사본을 받습니다.

내 버퍼가 레지스터로 가리켜지지 않는다면? (예제2: NtCreateFile)

getHook 함수는 버퍼와 그 크기에 대해 레지스터를 지정할 수 있지만, 어떤 경우에는 그렇지 않을 수 있습니다. NtCreateFile syscall을 가로채서 파일 이름을 얻고 싶다고 가정해 봅시다. NtCreateFile은 NTSTATUS NtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, ...) 형식을 따르며, 파일 이름은 ObjectAttributes->ObjectName->Buffer(크기는 ObjectAttributes->ObjectName->Length * sizeof(WCHAR))로 얻을 수 있습니다.

getHook은 또한 레지스터 대신 t1customOpcodes 매개변수에 셸코드를 지정할 수 있습니다. 이 셸코드는 다음을 따라야 합니다:

  • 버퍼 포인터를 RCX 레지스터에 배치;
  • 버퍼의 크기를 RDX 레지스터에 배치;
  • 스택을 망가뜨리지 않음.

NtCreateFile의 경우, 이 ASM 코드를 실행하여 작업을 수행할 수 있습니다:

root@kitploit:~
mov rax, [r8+0x10]    ; rax는 이제 ObjectAttributes->ObjectName
mov rcx, [rax + 0x10] ; rcx는 이제 ObjectAttributes->ObjectName->Buffer
mov rdx, [rax]        ; rdx는 이제 ObjectAttributes->ObjectName->Length
and rdx, 0xFFFF       ; Length는 USHORT
shl rdx, 1            ; 그리고 *2를 해야 함

이것을 어셈블리합시다 (예를 들어 온라인 디스어셈블리 웹사이트 사용): 498B4010488B4810488B104881E2FFFF000048D1E2. 이제 getHook 호출은 getHook(LocByName("NtCreateFile", t1customOpcodes="498B…E2")가 되어야 합니다.

여러 호출을 가로챌 수 있나요?

네! config 파일은 여러 가로채기 지점 정의를 포함할 수 있으며, getHook 함수는 파일에 추가됩니다. 여러 모듈에서 가로채기 지점을 설정할 수 있습니다. 예를 들어, ALPC와 IOCTL 메시지를 동시에 가로챌 수 있습니다.

Python 콜백에서 "메시지 ID"로 구분할 수 있습니다.

이런, BSOD/시스템 동결이 발생했습니다!

걱정하지 마세요. 실시간으로 테스트 케이스(및 수정 사항)를 원격 호스트로 보낼 수 있는 간단한 HTTP 서버(logserver.py)와 httpNetSend 함수도 있습니다.

퍼징은 어떻게 하나요?

bufferBitFlip 함수를 사용하여 몇 비트를 뒤집을 수 있습니다. 원시 메시지를 로깅하면 자체 디섹터를 작성하고 수동으로 더 나은 퍼저를 구현하는 데 도움이 됩니다. 버퍼 크기는 변경할 수 없다는 점을 기억하세요!

예를 들어, WriteFile 예제에서 다음 fuzzer 함수는 "hello"를 "world"로 대체합니다:

root@kitploit:~
def fuzzer(data, msgID=None, pid = 0):
   return data.replace("hello","world")

예제3: ALPC 메시지 분석

예를 들어, ALPC 메시지의 경우 다음 memitm.py 설정을 사용할 수 있습니다:

root@kitploit:~
def logger(data, msgID=None, pid=0):
    totalLen = 0
    dataLen = 0
    typ = 0
    dataInfoOffset = 0
    cid = 0
    tid = 0
    messageID = 0
    clientViewSize = 0
    # PORT_MESSAGE 헤더(0x18 바이트) 건너뛰기
    if len(data) > 0x18:
        totalLen = struct.unpack("<H",data[:2])[0]
        dataLen = struct.unpack("<H",data[2:4])[0]
        typ = struct.unpack("<H",data[4:6])[0]
        dataInfoOffset = struct.unpack("<H",data[6:8])[0]
        zeroInit = struct.unpack("<L",data[4:8])[0]
        cid = struct.unpack("<L",data[8:0xC])[0]
        tid = struct.unpack("<L",data[0xC:0x10])[0]
        messageID = struct.unpack("<L",data[0x10:0x14])[0]
        clientViewSize = struct.unpack("<L",data[0x14:0x18])[0]
    logMessage = "ALPC message : %x:%x - %x:%x - %d:%d - %x - %x" % (totalLen, dataLen, typ, dataInfoOffset, cid, tid, messageID, clientViewSize)
    print logMessage
    return

내부적으로 어떻게 작동하나요?

IDA Pro 스크립트에는 여러 명령어를 특정 영역으로 이동하는 간단한 "훅킹" 엔진이 포함되어 있습니다(DIMCT 도구에서 파생됨). 메모리 상대 명령어, 교차 참조 등과 같은 많은 경계 사례를 처리해야 하며, 여러 교차 참조가 포함된 정말 작은 기본 블록(x86 바이너리의 경우 <5바이트, x64 바이너리의 경우 <12바이트)을 가로채려고 하면 "여기에 훅을 설치할 수 없습니다"라는 메시지가 많이 표시될 것입니다. 자세한 내용은 소스 코드를 읽어보세요.

config 파일에 다음 정보를 생성합니다:

  • 모듈 이름;
  • 가로채기 지점의 상대 주소;
  • 가로채기 훅 영역("T1 트램폴린"이라고도 함): 버퍼/길이를 RCX/RDX에 배치하고 DLL 로그 루틴을 호출;
  • 복원 훅 영역("T2 트램폴린"이라고도 함): 컨텍스트를 복원하고 대체된 명령어를 실행한 후 가로채기 지점으로 돌아감;
  • 복원 훅 영역 재배치 정보: 절대 주소로 변환되어 패치되어야 하는 상대 명령어를 위한 것.

DLL 인젝터는 간단한 DLL 인젝터입니다(CreateRemoteThread/LoadLibraryA 방식).

DLL 자체는 공유 메모리 영역을 초기화하고 config 데이터를 기다립니다(공유 메모리 영역에는 3개의 일반 필드가 있습니다: 공유 메모리 메시지 ID, 메시지 크기, 메시지 버퍼). 데이터를 받으면 메모리에 훅을 구문 분석하고 설치하며, 이후에는 config 업데이트가 허용되지 않습니다(새 훅을 설정하려면 프로세스를 종료해야 함). 배치된 훅은 genericHookFunction DLL 함수로 연결됩니다. 이 함수는 메모리 영역(크리티컬 섹션으로 보호됨)을 버퍼 데이터, 크기 및 메시지 ID(공유 메모리 메시지 ID 필드의 상위 비트에 설정됨)로 채웁니다. Python 프로세스에 알리기 위해 두 개의 이벤트가 사용됩니다: 새 메시지를 알리기 위해 한 개, 프로세스가 패치할 때까지 기다리기 위해 다른 한 개(타임아웃 2초). 버퍼가 업데이트되면 원래 버퍼도 수정됩니다.

memitm.py 스크립트는 인젝터 프로세스를 실행하고 공유 메모리가 생성될 때까지 기다립니다. 그런 다음 구성을 보내고 메시지 이벤트를 기다립니다. 메시지가 수신되면 공유 메모리를 읽고 버퍼, 프로세스 ID 및 메시지 ID와 함께 logger 및 fuzzer 함수가 호출됩니다. logger 함수가 원래 버퍼와 다른 버퍼를 반환하고 크기가 같으면 공유 메모리 영역에 기록됩니다. 그런 다음 "ACK" 이벤트가 시그널링되고 스크립트는 새 메시지를 기다립니다.

이것으로 끝입니다!

이 도구가 유용하기를 바라며, 기여/리뷰는 언제나 환영합니다! 또한, 프랑스어를 사용하고 렌을 좋아한다면 저희는 채용 중입니다 :)

도구 다운로드