DLL
void ProcessDebugEvent( DEBUG_EVENT& debugEvent)
{
switch (debugEvent.dwDebugEventCode) {
case OUTPUT_DEBUG_STRING_EVENT: {
OUTPUT_DEBUG_STRING_INFO& info = debugEvent.u.DebugString;
char buffer[1024] = { 0 };
// 디버그 메시지를 읽기 위해 ReadProcessMemory 사용
if (info.fUnicode) {
// 유니코드 문자열 처리
WCHAR wBuffer[512] = { 0 };
SIZE_T bytesRead;
ReadProcessMemory(
OpenProcess(PROCESS_VM_READ, FALSE, debugEvent.dwProcessId),
info.lpDebugStringData,
wBuffer,
info.nDebugStringLength,
&bytesRead);
wprintf(L"[Debug] %s\n", wBuffer);
}
else {
// ANSI 문자열 처리
SIZE_T bytesRead;
ReadProcessMemory(
OpenProcess(PROCESS_VM_READ, FALSE, debugEvent.dwProcessId),
info.lpDebugStringData,
buffer,
info.nDebugStringLength,
&bytesRead);
printf("[Debug] %s\n", buffer);
}
break;
}
default:
break;
}
}
void RunServer()
{
LPCSTR slotName = "\\\\.\\mailslot\\SampleMailslot";
// 메일 슬롯 생성
HANDLE hMailslot = CreateMailslotA(
slotName, // 슬롯 이름
0, // 최대 메시지 크기 (0: 무제한)
MAILSLOT_WAIT_FOREVER, // 시간 초과 (무한 대기)
NULL // 보안 속성
);
if (hMailslot == INVALID_HANDLE_VALUE) {
std::cerr << "메일 슬롯 생성 실패: " << GetLastError() << std::endl;
return;
}
std::cout << "메일 슬롯이 생성되었습니다: " << slotName << std::endl;
CreateThread(NULL, 0, DebugThread, NULL, 0, NULL);
char buffer[256];
DWORD bytesRead;
while (true) {
DWORD nextSize, messageCount;
// 슬롯에 메시지가 있는지 확인
if (!GetMailslotInfo(hMailslot, NULL, &nextSize, &messageCount, NULL)) {
std::cerr << "메일 슬롯 정보 조회 실패: " << GetLastError() << std::endl;
break;
}
if (messageCount > 0 && nextSize != MAILSLOT_NO_MESSAGE) {
// 메시지 읽기
if (ReadFile(hMailslot, buffer, sizeof(buffer), &bytesRead, NULL)) {
buffer[bytesRead] = '\0';
DWORD processID = atoi(buffer);
gProcessIDs.push(processID);
std::cout << "받은 메시지: " << buffer << std::endl;
}
else {
std::cerr << "메일 슬롯 읽기 실패: " << GetLastError() << std::endl;
}
}
Sleep(1000); // CPU 사용률을 낮추기 위해 대기
}
CloseHandle(hMailslot);
return;
}
void SendProcessID(DWORD processID)
{
LPCSTR slotName = "\\\\.\\mailslot\\SampleMailslot";
// 메일 슬롯에 연결
HANDLE hFile = CreateFileA(
slotName, // 대상 메일 슬롯
GENERIC_WRITE, // 쓰기 권한
FILE_SHARE_READ, // 공유 모드
NULL, // 보안 속성
OPEN_EXISTING, // 기존 객체 열기
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
std::cerr << "메일 슬롯 연결 실패: " << GetLastError() << std::endl;
return;
}
std::cout << "메일 슬롯에 연결되었습니다." << std::endl;
// 메시지 전송
char message[64];// = "Hello, Mailslot!";
sprintf_s(message, 64, "%d", processID);
DWORD bytesWritten;
if (WriteFile(hFile, message, strlen(message), &bytesWritten, NULL)) {
std::cout << "메시지 전송 완료: " << message << std::endl;
}
else {
std::cerr << "메시지 전송 실패: " << GetLastError() << std::endl;
}
CloseHandle(hFile);
return;
}
DWORD WINAPI DebugThread(LPVOID lpParam) {
DEBUG_EVENT debugEvent;
while (1) {
while (!gProcessIDs.empty())
{
DWORD processID = gProcessIDs.front();
gProcessIDs.pop();
if (!DebugActiveProcess(processID)) {
printf("DebugActiveProcess failed: %d\n", GetLastError());
return 1;
}
}
while (TRUE) {
if (WaitForDebugEvent(&debugEvent, 1000)) {
ProcessDebugEvent(debugEvent);
ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
}
else {
break;
}
}
}
return 0;
}
Log Host App
RunServer();
Log Tester App
DWORD WINAPI DebugThread(LPVOID lpParam) {
DWORD pid = GetCurrentProcessId();
DWORD tid = GetCurrentThreadId();
std::string str;
DWORD i = 0;
while (i<1000) {
str = string_format("[PID:%d TID:%d] %d", pid, tid, i);
OutputDebugStringA(str.c_str());
i++;
}
return 0;
}
int main()
{
std::cout << "Test Start" << std::endl;
DWORD id = GetCurrentProcessId();
HANDLE thread[2];
SendProcessID(id);
Sleep(2000);
OutputDebugStringA("Test Start");
for (int i = 0;i < 2;i++) {
thread[i] = CreateThread(NULL, 0, DebugThread, NULL, 0, NULL);
}
WaitForMultipleObjects(2, thread, TRUE, INFINITE);
OutputDebugStringA("Test End");
try
{
//CauseError();
//OkB();
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught! Printing stack trace:" << std::endl;
std::cerr << "예외 발생: " << ex.what() << std::endl;
}
std::cout << "Test End" << std::endl;
return 0;
}