디버거 프로그램을 쓰다보면 bp(break point)를 자주 거는데
하드웨어 bp와 소프트웨어 bp가 있다.
하드웨어 bp는 4개까지 밖에 못 건다. 둘의 차이가 뭔지 왜 하드웨어 bp는 제한이 있는지 궁금했다.
일단 소프트웨어 bp는 명령어 0xcc이다.
Bp를 걸고싶은 명령어에 소프트웨어 bp를 걸면 디버거는 해당 명령어를 0xcc로 바꾸고 원본 바이트를 저장하여 사용자에게 보여준다.
0xcc 명령어가 실행되면 bp 명령어로 디버거에게 제어가 간다.
코드 상으론
LPDEBUG_EVENT pde
g_pfWriteFile = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile");
memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));
ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
&g_chOrgByte, sizeof(BYTE), NULL);
WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
&g_chINT3, sizeof(BYTE), NULL);
ReadProcessMemory로 원본 코드를 저장해두고, WriteProcessMemory로 해당 부분을 0xcc로 바꾸면 된다.
하드웨어 bp는 cpu에서 지원하는 bp로 cpu의 디버그 레지스터에 주소를 등록하는 방식으로 bp를 건다.
하드웨어bp를 위한 레지스터가 4개이기 때문에 4개까지 밖에 못 건다.
Cpu에 따라 다르지만 32비트 cpu에선 DR0~DR3가 bp를 위한 주소 저장
DR6은 디버그 상태 레지스터
DR7은 디버그 제어 레지스터로 DR레지스터를 조작하면 하드웨어 bp를 걸 수 있다.