
DLL 하이재킹을 쉽게 무기화하세요. 모든 DLL의 모든 함수를 백도어하세요.

DllShimmer는 원본 DLL을 파싱하여 내보낸 함수에 대한 정보(이름, 서수, 포워더 정보)를 추출합니다. 이 정보를 기반으로 DllShimmer는 C++ 보일러플레이트 파일(.cpp)을 생성합니다. 생성된 파일을 사용하면 프로그램의 정상적인 작동을 방해하지 않고 원본 DLL에서 내보낸 각 함수에 고유한 코드를 추가할 수 있습니다. DllShimmer는 함수 시그니처에 의존하지 않으므로 리버스 엔지니어링이나 인스트루멘테이션이 필요하지 않습니다("제한 사항"에서 자세히 참조).
두 번째로 생성되는 파일은 .def 파일로, 컴파일 후 프록시 DLL이 내보내는 모든 항목이 원본 DLL과 동일한 이름과 서수를 가지도록 보장합니다.
컴파일 후 프록시 DLL의 EAT는 원본 DLL의 EAT와 정확히 동일한 복사본입니다. 내보낸 함수의 모든 이름과 서수가 일치하며, 전달된 함수도 그대로 전달됩니다. DllShimmer는 대부분의 도구처럼 모든 함수를 명시적으로 전달하여 완전히 새롭고 의심스러운 EAT 구조를 만들지 않습니다.
Go 소스 코드를 컴파일하거나 컴파일된 바이너리를 다운로드하세요.
의존성:
x86_64-w64-mingw32-g++x86_64-w64-mingw32-dlltool예시:
# Backdoor version.dll (proxy to absolute path)
./DllShimmer -i version.dll -o project/ -x "C:/Windows/System32/version.dll" -m
# Backdoor random chat.dll (proxy to relative path)
./DllShimmer -i chat.dll -o project/ -x "lib/chat2.dll" -m
# Backdoor random app.dll (static linking to the original DLL)
./DllShimmer -i app.dll -o project/ -x "app2.dll" -m --static
매개변수:
-i / --input <path> [필수]
백도어를 심을 원본 DLL.
-o / --output <path> [필수]
DllShimmer가 생성된 모든 파일을 저장할 디렉터리 경로.
-x / --original <path> [필수]
동적 링킹(기본값)의 경우, 프록시 DLL이 대상 시스템에서 원본 DLL을 찾을 경로를 제공합니다.
정적 링킹(--static)의 경우, 원본 DLL의 이름만 지정하세요. Windows의 기본 로딩 순서에 따라 검색됩니다.
-m / --mutex [선택]
이 옵션을 활성화하면 소스 파일에 뮤텍스가 추가되어 단일 프로그램 실행 중 백도어가 두 번 이상 실행되는 것을 방지합니다. 모든 원본 함수는 정상적으로 계속 작동합니다.
--static [선택]
프록시 DLL(IAT)과 원본 DLL(EAT) 사이의 정적 링킹을 활성화합니다. 이렇게 하면 출력 디렉터리에 추가 .lib 파일이 생성되며, 이 파일은 정적 컴파일을 위한 원본 DLL 역할을 합니다.
이 기법은 동적 링킹에 비해 몇 가지 심각한 제한 사항이 있습니다.
그러나 정적 링킹은 일부 시나리오에서 더 은밀하고 자연스러울 수 있습니다.
기본값: DllShimmer는 항상 LoadLibraryA() 및 GetProcAddress() 함수를 사용하는 동적 링킹을 사용합니다.
--debug-file <path> [선택]
디버그 로그를 파일에 저장합니다. 프로그램이 실행되는 동안 로그가 지속적으로 파일에 기록됩니다. 선택하면 로그가 STDOUT에 출력되지 않습니다.
기본값: DllShimmer는 항상 디버그 로그를 STDOUT에 기록합니다.
디버그 출력 예시:

문제 해결을 시작하기 전에:
--static)을 사용하지 않도록 하십시오. 동적 링킹(기본값)으로 디버깅하는 것이 더 쉽습니다.--debug-file)..cpp 파일에 원본 DLL의 모든 내보낸 함수가 보이지 않습니다.원본 DLL에서 "전달(forwarded)"로 정의된 함수는 .cpp 파일에 포함되지 않습니다. 하지만 .def 파일에는 표시됩니다. 컴파일 후에는 원본 DLL에서와 동일하게 내보내집니다.
때때로 프록시 DLL이 원본 DLL을 로드할 때 오류를 표시하며, -x 매개변수에 이론상 올바른 상대 경로를 지정했는데도 오류 코드가 126입니다. 왜 작동하지 않는 걸까요?!?
DLL은 Current Directory에서 검색됩니다. 98%의 경우 이는 단순히 메인 EXE 파일의 위치이지만, 예를 들어 SetCurrentDirectoryW()를 사용하여 Current Directory를 임의로 변경하는 프로그램(대부분 오래된 레거시 프로그램)도 있습니다. 메인 프로그램은 이 변경을 알고 있으므로 프록시 DLL을 올바르게 로드하지만, 여러분은 이를 인지하지 못한 채 원본 DLL을 상대 경로로 로드하려고 하며, 프로그램은 변경된 Current Directory에서 이를 검색합니다.
이 규칙은 원본 DLL의 정적 및 동적 로딩 모두에 적용됩니다. 불행히도 정적 링킹에서는 디버그 정보가 없기 때문에 이 문제를 감지하기가 훨씬 어렵습니다. 시스템 로더는 그냥 실패하고 끝입니다. 그래서 저는 항상 기본 동적 링킹을 먼저 사용할 것을 권장합니다.
동적 링킹의 경우 두 가지 옵션이 있습니다.
-x 매개변수의 경로를 변경된 Current Directory 상황에 맞게 조정합니다.Current Directory를 동적으로 변경하여 원하는 위치에서 DLL을 검색합니다.정적 링킹의 경우 실제로는 한 가지 옵션만 있습니다.
Current Directory로 이동합니다.