Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New module to replicate xspy tool (and x11 library) #18877

Merged
merged 34 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
faa80dc
Create lib for X11.rb
h00die Feb 13, 2024
b22cafb
Update X11.rb
h00die Feb 13, 2024
6156fb5
Create spec for X11.rb
h00die Feb 13, 2024
c39d046
Update and rename X11.rb to x11.rb
h00die Feb 15, 2024
424c55f
Update x11.rb
h00die Feb 15, 2024
7330c69
Update and rename X11.rb to x11.rb
h00die Feb 15, 2024
f5a6d7d
Update x11.rb
h00die Feb 15, 2024
f4b698b
more progress, broke up lib x11 into different files/folders
h00die Feb 20, 2024
7292877
more progress, broke up lib x11 into different files/folders
h00die Feb 22, 2024
794e304
working but ugly code
h00die Feb 22, 2024
e7ca948
working xspy code
h00die Feb 22, 2024
d85f257
Thanks adfoster for spec fixes
h00die Feb 22, 2024
5e42df8
more x11 progress
h00die Feb 23, 2024
453f8bb
more x11 progress, now working on screenshots, WIP
h00die Feb 26, 2024
75d007b
WIP x11 screenshots and lib
h00die Feb 27, 2024
bd956e7
WIP x11 screenshots and lib
h00die Mar 1, 2024
69b89c5
WIP x11 screenshots and lib
h00die Mar 1, 2024
a524682
x11 screenshot module progress
h00die Mar 4, 2024
4f69034
remove screenshot functionality for time being
h00die Mar 22, 2024
bc9fdb3
docs
h00die Apr 14, 2024
7a27c0f
some review on x11
h00die Apr 22, 2024
417e7c1
x11 progress
h00die Apr 24, 2024
83d1dcb
move x11 to be more modular, forgot to grab spec files :(
h00die Apr 25, 2024
a7b428a
doc update
h00die Apr 25, 2024
45312a5
further x11 revisions
h00die Apr 26, 2024
80b4cb7
remove moved files
h00die May 1, 2024
05fb1d3
x11 library update
h00die Jul 11, 2024
ea0d400
update x11 docs
h00die Jul 11, 2024
04f4990
Further x11 updates
h00die Jul 11, 2024
a93a6dd
Merge branch 'rapid7:master' into xspy
h00die Jul 12, 2024
07cc3bb
Further updates to x11
h00die Jul 12, 2024
4ff3897
xspy updates
h00die Nov 21, 2024
cd4899d
Refactor some X11 code around
smcintyre-r7 Nov 27, 2024
e0a39b5
Merge pull request #26 from smcintyre-r7/pr/collab/18877
h00die Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions documentation/modules/auxiliary/gather/x11_keyboard_spy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
## Vulnerable Application

This module binds to an open X11 host to log keystrokes. The X11 service can accept
connections from any users when misconfigured with the command `xhost +`.
This module is a close copy of the old xspy c program which has been on Kali for a long time.
The module works by connecting to the X11 session, creating a background
window, binding a keyboard to it and creating a notification alert when a key
is pressed.

One of the major limitations of xspy, and thus this module, is that it polls
at a very fast rate. Faster than a key being pressed is released (especially before
the repeat delay is hit). To combat printing multiple characters for a single key
press, repeat characters are ignored.

### Ubuntu 10.04

1. `sudo nano /etc/gdm/gdm.schemas`
2. Find:

```
<schema>
<key>security/DisallowTCP</key>
<signature>b</signature>
<default>true</default>
</schema>
```
- Change `true` to `false`

3. logout or reboot
4. Verification: ```sudo netstat -antp | grep 6000```

```
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 1806/X
```

5. Now, to verify you allow ANYONE to get on X11, type: `xhost +`

### Ubuntu 12.04, 14.04

1. `sudo nano /etc/lightdm/lightdm.conf`
2. Under the `[SeatDefaults]` area, add:

```
xserver-allow-tcp=true
allow-guest=true
```

3. logout or reboot
4. Verification: ```sudo netstat -antp | grep 6000```

```
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 1806/X
```

5. Now, to verify you allow ANYONE to get on X11, type: `xhost +`

### Ubuntu 16.04

Use the Ubuntu 12.04 instructions, however change `SeatDefaults` to `Seat:*`

### Fedora 15

1. `vi /etc/gdm/custom.conf`
2. Under the `[security]` area, add:

```
DisallowTCP=false
```

3. logout/reboot
4. Now, to verify you allow ANYONE to get on X11, type: `xhost +`

### Solaris 10

1. `svccfg -s svc:/application/x11/x11-server setprop options/tcp_listen = true`
2. `svc disable cde-login`
3. `svc enable cde-login`
4. `xhost +`

### Ubuntu 22.04

#### Server

Getting X11 to listen on a TCP port is rather taxing, so we use socat to facilitate instead.

1. `sudo apt-get install ubuntu-desktop socat` # overkill but it gets everything we need
2. `sudo reboot` # prob a good idea since so much was installed
3. `sudo xhost +` # must be done through gui, not through SSH
4. `socat -d -d TCP-LISTEN:6000,fork,bind=<IP to listen to here> UNIX-CONNECT:/tmp/.X11-unix/X0`

## Verification Steps
Example steps in this format (is also in the PR):

1. Install the application
1. Start msfconsole
1. Do: `use [module path]`
1. Do: `run`
1. You should get a shell.

## Options
List each option and how to use it.

### Option Name

Talk about what it does, and how to use it appropriately. If the default value is likely to change, include the default value here.

## Scenarios
Specific demo of using the module that might be useful in a real world scenario.

### Version and OS

```
code or console output
```

For example:

To do this specific thing, here's how you do it:

```
msf > use module_name
msf auxiliary(module_name) > set POWERLEVEL >9000
msf auxiliary(module_name) > exploit
```

## Confirming

To keylog the remote host, we use a tool called [xspy](http://tools.kali.org/sniffingspoofing/xspy)
130 changes: 130 additions & 0 deletions lib/msf/core/exploit/remote/x11.rb
h00die marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# -*- coding: binary -*-

#
# This mixin is a simplistic implementation of X11
#
# Wireshark dissector: https://wiki.wireshark.org/X11
#

module Msf::Exploit::Remote::X11
include Msf::Exploit::Remote::X11::Connect
include Msf::Exploit::Remote::X11::Extensions
include Msf::Exploit::Remote::X11::Xkeyboard
include Msf::Exploit::Remote::X11::Keysymdef
include Msf::Exploit::Remote::X11::Window

class X11GETPROPERTYRESPONSE < BinData::Record
h00die marked this conversation as resolved.
Show resolved Hide resolved
endian :little
uint8 :reply
uint8 :format
uint16 :sequence_number # GetProperty
uint32 :reply_length
uint32 :get_property_type # 8bit boolean, \x01 == true \x00 == false
uint32 :bytes_after
uint32 :value_length
uint32 :unused
uint32 :unused1
uint32 :unused2
string :value_data, read_length: -> { value_length }
end

class X11GETPROPERTYREQUEST < BinData::Record
endian :little
uint8 :opcode, value: 20 # GetProperty
uint8 :delete_field, initial_value: 0 # \x00 false, assuming \x01 true?
uint16 :request_length, value: -> { num_bytes / 4 }
h00die marked this conversation as resolved.
Show resolved Hide resolved
uint32 :window # X11CONNECTION.screen_root
uint32 :property, initial_value: 23 # "\x17\x00\x00\x00" RESOURCE_MANAGER
uint32 :get_property_type, value: 31 # "\x1f\x00\x00\x00" # get-property-type (31 = string)
uint32 :long_offset, value: 0
uint32 :content_length, value: 100_000_000 # "\x00\xe1\xf5\x05"
end

class X11CREATEGRAPHICALCONTEXTREQUEST < BinData::Record
endian :little
uint8 :opcode, value: 55 # CreateGC (CreateGraphicalContext)
uint8 :unused
uint16 :request_length, value: -> { num_bytes / 4 }
uint32 :cid # X11CONNECTION.resource_id
uint32 :drawable # X11CONNECTION.screen_root
# gc-value-mask mappings from wireshark, uint32 total size
# .... .... .... .... .... .... .... ...0 = function: False
# .... .... .... .... .... .... .... ..0. = plane-mask: False
# .... .... .... .... .... .... .... .0.. = foreground: False
# .... .... .... .... .... .... .... 1... = background: True
# .... .... .... .... .... .... ...0 .... = line-width: False
# .... .... .... .... .... .... ..0. .... = line-style: False
# .... .... .... .... .... .... .0.. .... = cap-style: False
# .... .... .... .... .... .... 0... .... = join-style: False
# .... .... .... .... .... ...0 .... .... = fill-style: False
# .... .... .... .... .... ..0. .... .... = fill-rule: False
# .... .... .... .... .... .0.. .... .... = tile: False
# .... .... .... .... .... 0... .... .... = stipple: False
# .... .... .... .... ...0 .... .... .... = tile-stipple-x-origin: False
# .... .... .... .... ..0. .... .... .... = tile-stipple-y-origin: False
# .... .... .... .... .0.. .... .... .... = font: False
# .... .... .... .... 0... .... .... .... = subwindow-mode: False
# .... .... .... ...0 .... .... .... .... = graphics-exposures: False
# .... .... .... ..0. .... .... .... .... = clip-x-origin: False
# .... .... .... .0.. .... .... .... .... = clip-y-origin: False
# .... .... .... 0... .... .... .... .... = clip-mask: False
# .... .... ...0 .... .... .... .... .... = dash-offset: False
# .... .... ..0. .... .... .... .... .... = gc-dashes: False
# .... .... .0.. .... .... .... .... .... = arc-mode: False
bit1 :gc_value_mask_join_style, initial_value: 0
bit1 :gc_value_mask_cap_style, initial_value: 0
bit1 :gc_value_mask_line_style, initial_value: 0
bit1 :gc_value_mask_line_width, initial_value: 0
bit1 :gc_value_mask_background, initial_value: 0
bit1 :gc_value_mask_foreground, initial_value: 0
bit1 :gc_value_mask_plane_mask, initial_value: 0
bit1 :gc_value_mask_function, initial_value: 0

bit1 :gc_value_mask_subwindow_mode, initial_value: 0
bit1 :gc_value_mask_font, initial_value: 0
bit1 :gc_value_mask_tile_stipple_y_origin, initial_value: 0
bit1 :gc_value_mask_tile_stipple_x_origin, initial_value: 0
bit1 :gc_value_mask_stipple, initial_value: 0
bit1 :gc_value_mask_tile, initial_value: 0
bit1 :gc_value_mask_fill_rule, initial_value: 0
bit1 :gc_value_mask_fill_style, initial_value: 0

bit1 :gc_value_mask_arc_mode, initial_value: 0
bit1 :gc_value_mask_gc_dashes, initial_value: 0
bit1 :gc_value_mask_dash_offset, initial_value: 0
bit1 :gc_value_mask_clip_mask, initial_value: 0
bit1 :gc_value_mask_clip_y_origin, initial_value: 0
bit1 :gc_value_mask_clip_x_origin, initial_value: 0
bit1 :gc_value_mask_graphics_exposures, initial_value: 0
bit1 :gc_value_null_pad

bit8 :gc_value_null_pad1

uint32 :background, initial_value: 16777215
end

class X11FREEGRAPHICALCONTEXTREQUEST < BinData::Record
endian :little
uint8 :opcode, value: 60 #FreeGC
uint8 :unused, value: 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this needs to be 1 it's probably not unused.

uint16 :request_length, value: -> { num_bytes / 4 }
uint32 :gc # X11CONNECTION.resource_id_base
end

class X11GETINPUTFOCUSREQUEST < BinData::Record
endian :little
uint8 :opcode, value: 43 #GetInputFocus
uint8 :unused
uint16 :request_length, value: -> { num_bytes / 4 }
end

class X11INTERNATOMREQUEST < BinData::Record
endian :little
uint8 :opcode, value: 16 #InternAtom
uint8 :only_if_exists, initial_value: 0 # 0 false, 1 true?
uint16 :request_length, value: -> { num_bytes / 4 }
uint16 :name_length, value: -> { name.to_s.gsub(/\x00+\z/, '').length } # cut off the \x00 padding
uint16 :unused, initial_value: 0
string :name, trim_padding: true
end
end
102 changes: 102 additions & 0 deletions lib/msf/core/exploit/remote/x11/connect.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# -*- coding: binary -*-

#
# This mixin is a simplistic implementation of X11 initial connection protocol
#
# Wireshark dissector: https://wiki.wireshark.org/X11
#

module Msf::Exploit::Remote::X11::Connect
class X11VISUALTYPE < BinData::Record
endian :little
uint32 :visualid
uint8 :visual_type_classclass
uint8 :bits_per_rgb_value
uint16 :colormap_entries
uint32 :red_mask
uint32 :green_mask
uint32 :blue_mask
uint32 :unused
end

class X11DEPTHDETAIL < BinData::Record
endian :little
uint8 :depth
uint8 :unused
uint16 :visualtypes_numbers
uint32 :unused1
array :depth_detail,
type: :X11VISUALTYPE,
initial_length: :visualtypes_numbers
end

class X11PIXMAPFORMAT < BinData::Record
endian :little
uint8 :depth
uint8 :bits_per_pixel
uint8 :scanline_pad
uint8 :unused
uint32 :unused1
end

class X11CONNECTION < BinData::Record
h00die marked this conversation as resolved.
Show resolved Hide resolved
endian :little
uint8 :success # 8bit boolean, \x01 == true \x00 == false
uint8 :unused
uint16 :protocol_version_major
uint16 :protocol_version_minor
uint16 :reply_length
uint32 :release_number
uint32 :resource_id_base
uint32 :resource_id_mask
uint32 :motion_buffer_size
uint16 :vendor_length
uint16 :maximum_request_length
uint8 :number_of_screens_in_root
uint8 :number_of_formats_in_pixmap_formats
uint8 :image_byte_order
uint8 :bitmap_format_bit_order
uint8 :bitmap_format_scanline_unit
uint8 :bitmap_format_scanline_pad
uint8 :min_keycode
uint8 :max_keycode
uint32 :unused2
string :vendor, read_length: :vendor_length
array :pixmap_formats,
type: :X11PIXMAPFORMAT,
initial_length: :number_of_formats_in_pixmap_formats

# screen subsection
uint32 :screen_root
uint32 :screen_default_colormap
uint32 :screen_white_pixel
uint32 :screen_black_pixel
uint32 :screen_current_input_masks
uint16 :screen_width_in_pixels
uint16 :screen_height_in_pixels
uint16 :screen_width_in_millimeters
uint16 :screen_height_in_millimeters
uint16 :screen_min_installed_maps
uint16 :screen_max_installed_maps
uint32 :screen_root_visual
uint8 :screen_backing_stores
uint8 :screen_save_unders # 8bit boolean, \x01 == true \x00 == false
uint8 :screen_root_depth
uint8 :screen_allowed_depths_len
array :depth_detail,
type: :X11DEPTHDETAIL,
initial_length: :screen_allowed_depths_len
end

class X11CONNECTIONREQUEST < BinData::Record
# only 1/2 implemented since we dont have any authorization items added
endian :little
uint8 :byte_order, value: 108 # Little-endian
uint8 :unused, value: 0
uint16 :protocol_version_major, value: 11
uint16 :protocol_version_minor, value: 0
uint16 :authorization_protocol_name_length, value: 0
uint16 :authorization_protocol_data_length, value: 0
uint16 :unused2, value: 0
end
end
Loading
Loading