Skip to content

Commit

Permalink
split locking and notifies into separate cmds
Browse files Browse the repository at this point in the history
  • Loading branch information
katlogic committed Aug 9, 2016
1 parent 4543581 commit 625c2ed
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 40 deletions.
77 changes: 51 additions & 26 deletions driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ static int notify_unlock(int lock, CM_KEY_BODY *tkb, CM_KEY_BODY *kb)
return ret;
}

// Unlock/Lock registry key. This is slightly racey, don't use with busy keys.
static NTSTATUS unlock_key(PUNICODE_STRING name, int lock)
// Stop/reenable notifications on registry key.
static NTSTATUS reg_set_notify(PUNICODE_STRING name, int lock)
{
#define KLOCK_FLAGS (CM_KCB_NO_DELAY_CLOSE|CM_KCB_READ_ONLY_KEY)
#define KUNLOCK_MARKER (1<<15)
Expand All @@ -123,7 +123,7 @@ static NTSTATUS unlock_key(PUNICODE_STRING name, int lock)
OBJECT_ATTRIBUTES attr = {
.Length = sizeof(attr),
.Attributes = OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
.ObjectName = name,
.ObjectName = name
};
st = ZwOpenKey(&harr[i], KEY_READ, &attr);
if (!NT_SUCCESS(st))
Expand Down Expand Up @@ -175,25 +175,6 @@ static NTSTATUS unlock_key(PUNICODE_STRING name, int lock)
kl = kl->Flink;
}

DBG("lock=%d, kb=%p, cb=%p, t=%x refc=%u flags=%02x nb=%p\n",
lock, kb, cb, kb->Type, cb->RefCount, cb->ExtFlags, kb->NotifyBlock);

// Type 2 keys: Hard lock flag via NtLockRegistryKey public (!) syscall.
if (lock) {
if (!(cb->ExtFlags & KUNLOCK_MARKER))
goto out_unspam;
cb->ExtFlags &= ~KUNLOCK_MARKER;
cb->ExtFlags |= KLOCK_FLAGS;
st = STATUS_SUCCESS;
} else {
if (cb->ExtFlags & KUNLOCK_MARKER)
goto out_unspam;
if ((cb->ExtFlags & KLOCK_FLAGS) != KLOCK_FLAGS)
goto out_unspam;
cb->ExtFlags &= ~KLOCK_FLAGS;
cb->ExtFlags |= KUNLOCK_MARKER;
st = STATUS_SUCCESS;
}
out_unspam:;
i = NSPAM;
out_unspam_deref:
Expand All @@ -206,6 +187,48 @@ out_unspam:;
return st;
}

// Apply/remove hard lock.
static NTSTATUS reg_set_lock(PUNICODE_STRING name, int lock)
{
OBJECT_ATTRIBUTES attr = {
.Length = sizeof(attr),
.Attributes = OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
.ObjectName = name
};
HANDLE h;
NTSTATUS st;
CM_KEY_CONTROL_BLOCK *cb;
CM_KEY_BODY *kb;
st = ZwOpenKey(&h, KEY_READ, &attr);
if (!NT_SUCCESS(st))
return st;
st = ObReferenceObjectByHandle(h, KEY_WRITE,
*CmKeyObjectType, 0, (void*)&kb, NULL);

if (!NT_SUCCESS(st)) {
ZwClose(h);
return st;
}
cb = kb->KeyControlBlock;
st = STATUS_KEY_DELETED;
if (!cb || cb->Delete)
goto out;

DBG("lock=%d, kb=%p, cb=%p, t=%x refc=%u flags=%02x nb=%p\n",
lock, kb, cb, kb->Type, cb->RefCount, cb->ExtFlags, kb->NotifyBlock);

st = STATUS_SUCCESS;
if (lock) {
cb->ExtFlags |= KLOCK_FLAGS;
} else {
cb->ExtFlags &= ~KLOCK_FLAGS;
}
out:;
ObDereferenceObject(kb);
ZwClose(h);
return st;
}

static NTSTATUS change_prot(wind_prot_t *req)
{
int getonly;
Expand Down Expand Up @@ -280,11 +303,13 @@ switch (code) {
case WIND_IOCTL_INSMOD:
status = driver_sideload(&us);
break;
case WIND_IOCTL_REGLOCK:
status = unlock_key(&us, 1);
case WIND_IOCTL_REGLOCKON:
case WIND_IOCTL_REGLOCKOFF:
status = reg_set_lock(&us, (code>>2)&1);
break;
case WIND_IOCTL_REGUNLOCK:
status = unlock_key(&us, 0);
case WIND_IOCTL_REGNON:
case WIND_IOCTL_REGNOFF:
status = reg_set_notify(&us, (code>>2)&1);
break;
case WIND_IOCTL_PROT:
if (len != sizeof(wind_prot_t))
Expand Down
34 changes: 23 additions & 11 deletions wind.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,8 @@ static int usage(int interactive)
"This program can disable some restrictions of Windows:\n"
" * Driver signing ('DSE', breaks freeware utilities)\n"
" * Process protection ('unkillable processes', WinTCB)\n"
" * Read-only registry keys (malware is the only user)\n\n"
" * Hard locked registry keys (syscall, malware is the only user)\n\n"
" * Silently locked registry keys (notify, malware is the only user)\n\n"
);

if (!interactive) {
Expand All @@ -756,8 +757,11 @@ static int usage(int interactive)
" "BASENAME " /W run interactive installer\n"
" "BASENAME " /D <pid> de-protect specified PID\n"
" "BASENAME " /L [service|driver.sys] load unsigned driver and keep DSE status intact\n"
" "BASENAME " /RU <\\Registry\\Path> unlock registry key\n"
" "BASENAME " /RL <\\Registry\\Path> lock registry key\n");
" "BASENAME " /RD <\\Registry\\Path> R/O lock Disable\n"
" "BASENAME " /RE <\\Registry\\Path> R/O lock Enable\n"
" "BASENAME " /ND <\\Registry\\Path> Notify/refresh Disable\n"
" "BASENAME " /NE <\\Registry\\Path> Notify/refresh re-Enable\n"
);
goto out;
}

Expand Down Expand Up @@ -940,12 +944,12 @@ static int run_service()
return 1;
}

static int regunlock(WCHAR *p)
static int regunlock(int mcmd, WCHAR *p)
{
HANDLE dev;
NTSTATUS status;
int cmd = toupper(*p++);
if ((!cmd) || ((cmd != 'U') && (cmd != 'L')))
if ((!cmd) || ((cmd != 'E') && (cmd != 'D')))
usage(0);
while (*p == L' ' || *p == L'\t') p++;
dev = check_driver(0);
Expand All @@ -954,12 +958,18 @@ static int regunlock(WCHAR *p)
return 0;
}

if (cmd == 'U') {
if (cmd == 'D') {
printf("Unlocking %S...", p);
status = wind_ioctl_string(dev, WIND_IOCTL_REGUNLOCK, p);
status = wind_ioctl_string(dev,
mcmd=='N'
?WIND_IOCTL_REGNOFF
:WIND_IOCTL_REGLOCKOFF, p);
} else {
printf("Locking %S...", p);
status = wind_ioctl_string(dev, WIND_IOCTL_REGLOCK, p);
status = wind_ioctl_string(dev,
mcmd=='N'
?WIND_IOCTL_REGNON
:WIND_IOCTL_REGLOCKON, p);
}
if (NT_SUCCESS(status))
printf("OK\n");
Expand All @@ -971,7 +981,7 @@ static int regunlock(WCHAR *p)

void ENTRY(win_main)()
{
int ret = 0;
int cc, ret = 0;
CONSOLE_SCREEN_BUFFER_INFO csbi;
int explorer = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)
&& !(csbi.dwCursorPosition.X|csbi.dwCursorPosition.Y);
Expand All @@ -988,7 +998,8 @@ void ENTRY(win_main)()
usage(explorer);
cmd += 2;

switch (toupper(cmd[-1])) {
cc = toupper(cmd[-1]);
switch (cc) {
case 'I':
ret = !!do_install();
break;
Expand All @@ -1008,7 +1019,8 @@ void ENTRY(win_main)()
ret = !!unprotect(cmd);
break;
case 'R':
ret = !!regunlock(cmd);
case 'N':
ret = !!regunlock(cc, cmd);
break;
default:
usage(0);
Expand Down
9 changes: 6 additions & 3 deletions wind.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ typedef struct {
// Load a driver. Argument is simply the unicode string.
#define WIND_IOCTL_INSMOD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)

// Lock/Unlock registry key.
#define WIND_IOCTL_REGLOCK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define WIND_IOCTL_REGUNLOCK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Lock/Unlock registry key. Odd ones are the 'on' command.
#define WIND_IOCTL_REGLOCKON CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define WIND_IOCTL_REGLOCKOFF CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define WIND_IOCTL_REGNON CTL_CODE(FILE_DEVICE_UNKNOWN, 0x813, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define WIND_IOCTL_REGNOFF CTL_CODE(FILE_DEVICE_UNKNOWN, 0x814, METHOD_BUFFERED, FILE_ANY_ACCESS)


// Get/set WinTcb process protection.
#define WIND_IOCTL_PROT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
Expand Down

0 comments on commit 625c2ed

Please sign in to comment.