Skip to content

Commit

Permalink
Made the detection of Ctrl+Alt+F4 more secure.
Browse files Browse the repository at this point in the history
Made the log much more compact.
Now getting SeDebugPrivilege when dll loads.
Only one instance can be run, tray icon of first instance is readded.
Released 0.8.
  • Loading branch information
stefansundin committed Sep 16, 2008
1 parent ec7ae96 commit 331b195
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 263 deletions.
3 changes: 1 addition & 2 deletions SuperF4.exe.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="SuperF4"
name="XP style"
type="win32" />
<description>SuperF4</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
Expand Down
6 changes: 5 additions & 1 deletion info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ You can use -hide as a parameter to hide the tray icon.

Changelog
---------
0.8:
Made the detection of Ctrl+Alt+F4 more secure, preventing faulty kills which could happen when SuperF4 didn't receive the keyup of the F4 key.
Only one instance of SuperF4 can now be run. Starting SuperF4 again will make the first instance add its tray icon if hidden.

0.7:
keyhook now tries to get the SeDebugPrivilege privilege if OpenProcess fails, should be able to kill more programs.
keyhook now tries to get the SeDebugPrivilege privilege, allowing more programs to be killed.

0.6:
Small fix to prevent the key pressed from being propagated to another window after terminating the process.
Expand Down
269 changes: 100 additions & 169 deletions keyhook.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@

static int ctrl=0;
static int alt=0;
static int f4=0;
static char msg[100];
static FILE *output;

BOOL SetPrivilege(HANDLE hToken, LPCTSTR priv, BOOL bEnablePrivilege) {
TOKEN_PRIVILEGES tp;
Expand Down Expand Up @@ -63,6 +63,15 @@ BOOL SetPrivilege(HANDLE hToken, LPCTSTR priv, BOOL bEnablePrivilege) {
return TRUE;
}

char* GetTimestamp(char *buf, size_t maxsize, char *format) {
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo=localtime(&rawtime);
strftime(buf,maxsize,format,timeinfo);
return buf;
}

_declspec(dllexport) LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
int vkey=((PKBDLLHOOKSTRUCT)lParam)->vkCode;
Expand All @@ -75,191 +84,113 @@ _declspec(dllexport) LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPA
if (vkey == VK_MENU || vkey == VK_LMENU || vkey == VK_RMENU) {
alt=1;
}
if (vkey == VK_F4) {
f4=1;
}
}
else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
if (vkey == VK_CONTROL || vkey == VK_LCONTROL || vkey == VK_RCONTROL) {
ctrl=0;
}
if (vkey == VK_MENU || vkey == VK_LMENU || vkey == VK_RMENU) {
alt=0;
}
if (vkey == VK_F4) {
f4=0;
}
}

//Double check that Ctrl and Alt are pressed
//This prevents a faulty kill if keyhook haven't received the KEYUP for these keys
if (ctrl && alt && f4) {
if (!(GetAsyncKeyState(VK_CONTROL)&0x8000)) {
ctrl=0;
}
else if (!(GetAsyncKeyState(VK_MENU)&0x8000)) {
alt=0;
}
/*else if (!(GetAsyncKeyState(VK_F4)&0x8000)) {
f4=0;
}*/
}

//This will happen if Ctrl+Alt+F4 is being pressed
if (ctrl && alt && f4) {
//Open log
FILE *output;
if ((output=fopen("log-keyhook.txt","ab")) == NULL) {
sprintf(msg,"Failed to open log file.\nfopen() failed in file %s, line %d.",__FILE__,__LINE__);
MessageBox(NULL, msg, "SuperF4 Warning", MB_ICONWARNING|MB_OK);
}

if (output != NULL) {
//Print timestamp
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo=localtime(&rawtime);
strftime(msg,sizeof(msg),"[%Y-%m-%d %H:%M:%S]",timeinfo);
fprintf(output,"\n%s\n",msg);

fprintf(output,"Ctrl+Alt+F4 pressed!\n");
}

//Get hwnd of foreground window
HWND hwnd;
if ((hwnd=GetForegroundWindow()) == NULL) {
sprintf(msg,"GetForegroundWindow() failed in file %s, line %d.",__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"%s\n",msg);
fclose(output);
if (ctrl && alt && vkey == VK_F4) {
//Double check that Ctrl and Alt are pressed
//This prevents a faulty kill if keyhook haven't received the keyup for these keys
if (!(GetAsyncKeyState(VK_CONTROL)&0x8000)) {
ctrl=0;
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
return 0;
}

//Get hwnd title (for log)
if (output != NULL) {
char title[100];
GetWindowText(hwnd,title,100);
fprintf(output,"Window title: %s\n",title);
}

//Get process id of hwnd
DWORD pid;
GetWindowThreadProcessId(hwnd,&pid);
if (output != NULL) {
fprintf(output,"Process id: %d\n",pid);
fprintf(output,"Opening process... ");
}

HANDLE process;
if ((process=OpenProcess(PROCESS_TERMINATE,FALSE,pid)) == NULL) {
if (output != NULL) {
fprintf(output,"failed! (error: %d)\n",GetLastError());
fprintf(output,"Attempting to aquire SeDebugPrivilege privilege... ");
else if (!(GetAsyncKeyState(VK_MENU)&0x8000)) {
alt=0;
}

//Get token
HANDLE hToken;
if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken) == 0) {
if (GetLastError() == ERROR_NO_TOKEN) {
if (ImpersonateSelf(SecurityImpersonation) == 0) {
sprintf(msg,"ImpersonateSelf() failed (error: %d) in file %s, line %d.",GetLastError(),__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"failed!\n%s\n",msg);
fclose(output);
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
return 0;
}

if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken) == 0) {
sprintf(msg,"OpenThreadToken() failed (error: %d) in file %s, line %d.",GetLastError(),__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"failed!\n%s\n",msg);
fclose(output);
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
return 0;
}
else {
//Kill program
fprintf(output,"%s ",GetTimestamp(msg,sizeof(msg),"[%Y-%m-%d %H:%M:%S]"));

//Get hwnd of foreground window
HWND hwnd;
if ((hwnd=GetForegroundWindow()) == NULL) {
fprintf(output,"Error: GetForegroundWindow() failed in file %s, line %d.",__FILE__,__LINE__);
fflush(output);
return 0;
}
else {
sprintf(msg,"OpenThreadToken() failed (error: %d) in file %s, line %d.",GetLastError(),__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"failed!\n%s\n",msg);
fclose(output);
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);

//Get hwnd title (for log)
char title[100];
GetWindowText(hwnd,title,100);

//Get process id of hwnd
DWORD pid;
GetWindowThreadProcessId(hwnd,&pid);

fprintf(output,"Killing \"%s\" (pid %d)... ",title,pid);

//Open the process
HANDLE process;
if ((process=OpenProcess(PROCESS_TERMINATE,FALSE,pid)) == NULL) {
fprintf(output,"failed!\n");
fprintf(output,"Error: OpenProcess() failed (error: %d) in file %s, line %d.\n",GetLastError(),__FILE__,__LINE__);
fflush(output);
return 0;
}
}

//Enable SeDebugPrivilege
if (SetPrivilege(hToken, SE_DEBUG_NAME, TRUE) == FALSE) {
sprintf(msg,"SetPrivilege() failed (error: %d) in file %s, line %d.",GetLastError(),__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"failed!\n%s\n",msg);
fclose(output);

//Terminate process
if (TerminateProcess(process,1) == 0) {
fprintf(output,"failed!\n");
fprintf(output,"Error: TerminateProcess() failed (error: %d) in file %s, line %d.\n",GetLastError(),__FILE__,__LINE__);
fflush(output);
return 0;
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
CloseHandle(hToken);
return 0;
}
CloseHandle(hToken);

//Try to open process again
if (output != NULL) {

fprintf(output,"success!\n");
fprintf(output,"Opening process... ");
}
if ((process=OpenProcess(PROCESS_TERMINATE,FALSE,pid)) == NULL) {
sprintf(msg,"OpenProcess() failed (error: %d) in file %s, line %d.",GetLastError(),__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"failed!\n%s\n",msg);
fclose(output);
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
return 0;
fflush(output);

//Prevent this keypress from being propagated to the window selected after the kill
return 1;
}
}

//Terminate process
if (output != NULL) {
fprintf(output,"success!\n");
fprintf(output,"Killing process... ");
}
if (TerminateProcess(process,1) == 0) {
sprintf(msg,"TerminateProcess() failed (error: %d) in file %s, line %d.",GetLastError(),__FILE__,__LINE__);
if (output != NULL) {
fprintf(output,"failed!\n%s\n",msg);
fclose(output);
}
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
return 0;
}
else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
if (vkey == VK_CONTROL || vkey == VK_LCONTROL || vkey == VK_RCONTROL) {
ctrl=0;
}

if (output != NULL) {
fprintf(output,"success!\n");

//Close log
if (fclose(output) == EOF) {
sprintf(msg,"fclose() failed in file %s, line %d.",__FILE__,__LINE__);
fprintf(output,"%s\n",msg);
fclose(output);
MessageBox(NULL, msg, "SuperF4 Error", MB_ICONERROR|MB_OK);
return 0;
}
if (vkey == VK_MENU || vkey == VK_LMENU || vkey == VK_RMENU) {
alt=0;
}

//Prevent this keypress from being propagated to the window selected after the kill
return 1;
}
}

return CallNextHookEx(NULL, nCode, wParam, lParam);
}

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
//Open log
output=fopen("log-keyhook.txt","ab");
fprintf(output,"\n%s ",GetTimestamp(msg,sizeof(msg),"[%Y-%m-%d %H:%M:%S]"));
fprintf(output,"New session. Getting SeDebugPrivilege privilege... ");

//Create security context
if (ImpersonateSelf(SecurityImpersonation) == 0) {
fprintf(output,"failed!\n");
fprintf(output,"Error: ImpersonateSelf() failed (error: %d) in file %s, line %d.\n",GetLastError(),__FILE__,__LINE__);
fflush(output);
return TRUE;
}
//Get access token
HANDLE hToken;
if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken) == 0) {
fprintf(output,"failed!\n");
fprintf(output,"Error: OpenThreadToken() failed (error: %d) in file %s, line %d.\n",GetLastError(),__FILE__,__LINE__);
fflush(output);
return TRUE;
}
//Enable SeDebugPrivilege
if (SetPrivilege(hToken, SE_DEBUG_NAME, TRUE) == FALSE) {
fprintf(output,"failed!\n");
fprintf(output,"Error: SetPrivilege() failed (error: %d) in file %s, line %d.\n",GetLastError(),__FILE__,__LINE__);
fflush(output);
CloseHandle(hToken);
return TRUE;
}
CloseHandle(hToken);
fprintf(output,"success!\n");
fflush(output);
}
else if (reason == DLL_PROCESS_ATTACH) {
//Close log
fclose(output);
}

return TRUE;
}
6 changes: 3 additions & 3 deletions resources.rc
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "SuperF4.exe.manifest"

#define VS_VERSION_INFO 1
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,7,0,0
PRODUCTVERSION 0,7,0,0
FILEVERSION 0,8,0,0
PRODUCTVERSION 0,8,0,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
Expand All @@ -21,7 +21,7 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "SuperF4"
VALUE "FileVersion", "0.7"
VALUE "FileVersion", "0.8"
VALUE "InternalName", "superf4"
VALUE "LegalCopyright", "� Stefan Sundin 2008"
VALUE "OriginalFilename", "SuperF4.exe"
Expand Down
Loading

0 comments on commit 331b195

Please sign in to comment.