Skip to content

Commit 98ec7f9

Browse files
committed
initial commit
0 parents  commit 98ec7f9

19 files changed

Lines changed: 2146 additions & 0 deletions

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.vs
2+
.lib
3+
.x64
4+
*.vcxproj.user

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "minhook"]
2+
path = minhook
3+
url = https://github.com/TsudaKageyu/minhook

Breakpoint.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#include "Breakpoint.h"
2+
3+
// ----------------------------------------------------------------------------
4+
Breakpoint::Breakpoint(DWORD tid, void* addr, UCHAR type)
5+
{
6+
m_hThread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, tid);
7+
m_nIndex = -1;
8+
this->set(addr, type);
9+
this->enable();
10+
}
11+
12+
// ----------------------------------------------------------------------------
13+
Breakpoint::~Breakpoint()
14+
{
15+
this->disable();
16+
CloseHandle(m_hThread);
17+
}
18+
19+
// ----------------------------------------------------------------------------
20+
bool Breakpoint::set(void* addr, UCHAR type)
21+
{
22+
m_pAddr = addr;
23+
m_nType = type;
24+
25+
if (this->enabled())
26+
{
27+
// update existing breakpoint
28+
return this->enable();
29+
}
30+
31+
return true;
32+
}
33+
34+
// ----------------------------------------------------------------------------
35+
bool Breakpoint::enable()
36+
{
37+
BOOL ok = false;
38+
39+
SuspendThread(m_hThread);
40+
41+
CONTEXT ctx = { 0 };
42+
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
43+
if (GetThreadContext(m_hThread, &ctx))
44+
{
45+
ok = true;
46+
auto index = -1;
47+
48+
if (this->enabled()) index = m_nIndex;
49+
else if (!(ctx.Dr7 & 0x01)) index = 0;
50+
else if (!(ctx.Dr7 & 0x04)) index = 1;
51+
else if (!(ctx.Dr7 & 0x10)) index = 2;
52+
else if (!(ctx.Dr7 & 0x40)) index = 3;
53+
54+
switch (index)
55+
{
56+
default:
57+
ok = false;
58+
break;
59+
60+
case 0:
61+
ctx.Dr0 = (DWORD64)m_pAddr;
62+
ctx.Dr7 &= 0xFFF0FFFC;
63+
ctx.Dr7 |= (m_nType << 16) | 0x01;
64+
break;
65+
66+
case 1:
67+
ctx.Dr1 = (DWORD64)m_pAddr;
68+
ctx.Dr7 &= 0xFF0FFFF3;
69+
ctx.Dr7 |= (m_nType << 20) | 0x04;
70+
break;
71+
72+
case 2:
73+
ctx.Dr2 = (DWORD64)m_pAddr;
74+
ctx.Dr7 &= 0xF0FFFFCF;
75+
ctx.Dr7 |= (m_nType << 24) | 0x10;
76+
break;
77+
78+
case 3:
79+
ctx.Dr3 = (DWORD64)m_pAddr;
80+
ctx.Dr7 &= 0x0FFFFF3F;
81+
ctx.Dr7 |= (m_nType << 28) | 0x40;
82+
break;
83+
}
84+
85+
ctx.Dr6 = 0;
86+
if (ok &= SetThreadContext(m_hThread, &ctx))
87+
{
88+
m_nIndex = index;
89+
}
90+
}
91+
92+
ResumeThread(m_hThread);
93+
94+
return ok;
95+
}
96+
97+
// ----------------------------------------------------------------------------
98+
bool Breakpoint::disable()
99+
{
100+
BOOL ok = false;
101+
102+
SuspendThread(m_hThread);
103+
104+
CONTEXT ctx = { 0 };
105+
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
106+
if (GetThreadContext(m_hThread, &ctx))
107+
{
108+
ok = true;
109+
110+
switch (m_nIndex)
111+
{
112+
default:
113+
ok = false;
114+
break;
115+
116+
case 0:
117+
ctx.Dr7 &= 0xFFF0FFFC;
118+
break;
119+
120+
case 1:
121+
ctx.Dr7 &= 0xFF0FFFF3;
122+
break;
123+
124+
case 2:
125+
ctx.Dr7 &= 0xF0FFFFCF;
126+
break;
127+
128+
case 3:
129+
ctx.Dr7 &= 0x0FFFFF3F;
130+
break;
131+
}
132+
133+
ctx.Dr6 = 0;
134+
if (ok &= SetThreadContext(m_hThread, &ctx))
135+
{
136+
m_nIndex = -1;
137+
}
138+
}
139+
140+
ResumeThread(m_hThread);
141+
142+
return ok;
143+
}

Breakpoint.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <Windows.h>
4+
5+
class Breakpoint
6+
{
7+
public:
8+
enum Type
9+
{
10+
Exec = 0x0,
11+
Write = 0x1,
12+
ReadWrite = 0x3,
13+
14+
Size1 = 0x0,
15+
Size2 = 0x4,
16+
Size4 = 0xC,
17+
Size8 = 0x8,
18+
19+
AccessMask = 0x3,
20+
SizeMask = 0xC
21+
};
22+
23+
Breakpoint(DWORD tid, void* addr, UCHAR type);
24+
~Breakpoint();
25+
26+
bool set(void* addr, UCHAR type);
27+
bool enable();
28+
bool disable();
29+
30+
bool enabled() const { return m_nIndex >= 0 && m_nIndex < 4; }
31+
void* addr() const { return m_pAddr; }
32+
UCHAR type() const { return m_nType; }
33+
UCHAR access() const { return m_nType & AccessMask; }
34+
UCHAR size() const { return m_nType & SizeMask; }
35+
HANDLE thread() const { return m_hThread; }
36+
37+
private:
38+
HANDLE m_hThread;
39+
void* m_pAddr;
40+
UCHAR m_nType;
41+
CHAR m_nIndex;
42+
};

COPYING.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2021 Devin Acker
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

0 commit comments

Comments
 (0)