오늘 화났쩌
중요 프로젝트 파일을 분실하여 화가 나버렸어요.
창고에 hdd를 꺼내서 들여다 보아도 전혀 안 나와요. 망했쩌 ..
rdp wrapper 주제에 관련하여 데스크탑 윈도우 버전에 원격데스크탑 세션이 하나로 제한되어 있는데 이케이케 풀어주는 크랙 .. 떳떳한 주제는 아니지 않나요. 자동화에 중요한 부분이어서 어쩔 수가 없어요.
rdp wrapper는 설마 델파이로 만들었나 .. 래퍼 dll은 c++를 사용하고 gui를 델파이로 만들었나 보아요. 라자루스로 만들었을 수도 있지 않겠나요.
이 프로젝트는 정적 포인터 설정 파일과 패치 어레이를 가지고 termsrv.dll 버전에 맞는 패치를 적용해요.
[1] GitHub - stascorp/rdpwrap: RDP Wrapper Library
사실 데스크탑 윈도우는 자동 업데이트가 자주 되어서 이런 멍청한 방법은 적절하지 않을 것으로 전망해요. 이렇다 하여서 프로세스 메모리 섹션 스캐너를 만들고 목적 루틴에 패치를 하였는데요. 잼민이때 만든 고대 소스를 잊어버려서 화가났고 처음부터 새로 썻어요.
사실머 핵심 코드는 rdp wrapper와 공통 부분이 많은데요.
중요 로직이 없어져서 옛 버전 wrap.dll을 x64dbg로 열어서 뜯고 맛보았어요.
Source.def
LIBRARY
EXPORTS
ServiceMain
SvchostPushServiceGlobalsmain.cpp
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
auto hTermSrv = LoadLibraryA(termsrv_dll);
size_t addr, size;
DWORD protect;
return true;
}
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) {
auto hTermSrv = GetModuleHandleA(termsrv_dll);
if (hTermSrv != nullptr) {
auto proc = GetProcAddress(hTermSrv, "ServiceMain");
if (proc != nullptr) {
((SERVICEMAIN)proc)(dwArgc, lpszArgv);
}
}
}
void WINAPI SvchostPushServiceGlobals(void* lpGlobalData) {
auto hTermSrv = GetModuleHandleA(termsrv_dll);
if (hTermSrv != nullptr) {
auto proc = GetProcAddress(hTermSrv, "SvchostPushServiceGlobals");
if (proc != nullptr) {
((SVCHOSTPUSHSERVICEGLOBALS)proc)(lpGlobalData);
}
}
} PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_FILE_HEADER pFileHeader;
PIMAGE_OPTIONAL_HEADER pOptionalHeader;
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
pFileHeader = (PIMAGE_FILE_HEADER)(((PBYTE)hModule) + pDosHeader->e_lfanew + 4);
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)(pFileHeader + 1);
// Output
BaseAddr = pOptionalHeader->ImageBase + pOptionalHeader->BaseOfCode;
BaseSize = pOptionalHeader->SizeOfCode;이 코드는 실행 파일의 헤더 정보를 가져오는 코드입니다. PE 헤더를 읽어와 실행 파일의 기본 주소와 크기를 계산합니다.
다음은 코드의 각 부분을 설명한 것입니다:
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_FILE_HEADER pFileHeader;
PIMAGE_OPTIONAL_HEADER pOptionalHeader;
이것은 실행 파일의 헤더 구조체 포인터를 선언합니다. PIMAGE_DOS_HEADER는 DOS 헤더 구조체, PIMAGE_FILE_HEADER는 파일 헤더 구조체, PIMAGE_OPTIONAL_HEADER는 선택적 헤더 구조체에 대한 포인터입니다.
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
pDosHeader 포인터를 모듈 핸들 hModule에 대한 PIMAGE_DOS_HEADER 포인터로 설정합니다.
pFileHeader = (PIMAGE_FILE_HEADER)(((PBYTE)hModule) + pDosHeader->e_lfanew + 4);
pFileHeader 포인터를 파일 헤더 구조체의 시작 부분으로 설정합니다. 이 주소는 hModule의 포인터를 pDosHeader->e_lfanew와 4를 더한 값으로 계산됩니다.
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)(pFileHeader + 1);
pOptionalHeader 포인터를 선택적 헤더 구조체의 시작 부분으로 설정합니다. 이 주소는 pFileHeader에 1을 더한 값으로 계산됩니다.
BaseAddr = pOptionalHeader->ImageBase + pOptionalHeader->BaseOfCode;
BaseSize = pOptionalHeader->SizeOfCode;
이것은 실행 파일의 기본 주소와 크기를 계산합니다. 기본 주소는 pOptionalHeader->ImageBase와 pOptionalHeader->BaseOfCode의 합으로 계산되며, 크기는 pOptionalHeader->SizeOfCode로 계산됩니다.
이 코드는 PE 헤더를 읽어와 실행 파일의 기본 주소와 크기를 계산하는 데 사용됩니다.
이거 맞냐 .. 뭐 대충 맞는 것 같아요. 실제 pe는 더 복잡하게 생겨 먹어서 보기가 싫어져요.
메인 소스가 100줄 언저리에 코드이어서 극대노 까지는 가지 않아도 되어요. 이 정도면 선방 하였겠어요.
이케 새로 쓴 프로그램에 기능을 좀 더 넣으면 불법일 것인데, ms가 이제는 오픈소스를 개척 중이어서 심하게 뭐라고 하진 않겠쩌. 레지스트리를 건드려서 포트를 변경할 수 있지만, 요즘 누가 일일이 레지스트리 설정을 건드리러 가나요. json 설정 파일로 저장하고 포트 번호 변경, rdp over udp 이런 기능을 긍정적으로 전망해요.
음 ..
