-
Notifications
You must be signed in to change notification settings - Fork 14k
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
base: master
Are you sure you want to change the base?
Conversation
I'll give this another check tomorrow, I know some of the reviews have some notes to touch up, but I think its ready for review. I'm going to do an x11 screenshot taker as well, so some of the lib functions aren't used yet, but wanted to get this in framework first before it gets too out of hand. |
@smcintyre-r7 you can go ahead and start reviewing. I know I need to update the open_x11 scanner docs, and a few other minor things. figured this may take a little bit since its so large |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left quite a few comments, but overall things are looking pretty good. Thanks for this new protocol!
got through some, just an update that I'm working on it, its not abandoned :) |
prob worth a squash when this is ready to merge, no one needs to see 31+ commits where I learn to code gooderer. |
I believe this is ready to look at again. It's undergone a lot of changes, so may want to treat it as a fresh PR. |
|
||
print_good('All setup, watching for keystrokes') | ||
# loop mechanics stolen from exploit/multi/handler | ||
stime = Time.now.to_f |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be great to use Process.clock_gettime(Process::CLOCK_MONOTONIC)
instead of these Time.now
calls 👍
https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
def create_overlay_map(screen_width, screen_height, windows) | ||
# Initialize a 2D array to represent the screen | ||
screen = Array.new(screen_height) { Array.new(screen_width, nil) } | ||
windows.each_with_index do |window, i| | ||
puts window.inspect | ||
x, y, width, height = window | ||
# Mark the visible region occupied by the window | ||
(y...y + height).each do |row| | ||
(x...x + width).each do |col| | ||
screen[row][col] = i | ||
end | ||
end | ||
end | ||
screen.each do |row| | ||
puts row.join('') | ||
end | ||
end | ||
|
||
class X11Image | ||
def initialize(width, height, image_data, color_data) | ||
@width = width # integer, 1024 in 1024×768 | ||
@height = height # integer, 768 in 1024×768 | ||
@image_data = image_data # from X11GetImageResponse | ||
@color_data = color_data # from X11GetColorsResponse | ||
end | ||
|
||
def self.from_replies(width, height, image_reply, color_reply) | ||
new(width, height, image_reply.image_data, color_reply.colors) | ||
end | ||
|
||
def create_image | ||
# Extract relevant data from @image_data and @color_data | ||
width = @width | ||
height = @height | ||
pixel_data = @image_data | ||
colors = @color_data | ||
|
||
# Create an image object | ||
image = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT) | ||
|
||
# Populate image with pixel data and colors | ||
pixel_data.each_with_index do |pixel, i| | ||
color = colors[pixel] | ||
# Set pixel color in the image | ||
image[i % width, i / width] = ChunkyPNG::Color.rgb(color.red, color.green, color.blue) | ||
end | ||
# (0...height).each do |y| | ||
# (0...width).each do |x| | ||
# # Extract color information from the pixel data and set the corresponding pixel in the PNG image | ||
# color = colors[y+x] | ||
# # pixel_color = extract_color_from_z_data(z_data) | ||
# image[x, y] = ChunkyPNG::Color.rgb(color.red, color.green, color.blue) | ||
# end | ||
# end | ||
|
||
image | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see where either of these are referenced, so it may be safe to remove them unless I'm not seeing something. The reason I was looking into it, is that if we need to keep the definitions, we should move them so they're not defined globally. If I can see where they're referenced, I can make better recommendations on how to move them to someplace sensible.
rescue ::Rex::ConnectionError | ||
rescue ::Errno::EPIPE | ||
if connection.header.success == 1 | ||
print_connection_info(connection, ip, rport) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't report it as a service but as a note. The scanner here should definitely report it as a service since that's probably the context in which this module would be used. I'd either recommend updating #print_connection_info
to report the service, or report it here.
I'm inconsistently getting the following stack trace. My target is an Ubuntu 22.04 x64 workstation where I installed socat. It seems like it's easier to reproduce the stack trace after rebooting. If I run the module a couple of times without rebooting the target, it'll work after 1 or 2 failures. EOF Stack Trace
PCap of the transaction when the stack trace occurred. It may be simple enough to handle the EOF and carry on, I'm not entirely sure. I've definitely seen the module work, it's just this crash sometimes. |
This PR implements a rudimentary pure ruby X11 library, and a module to bind to open x11 sessions to perform keylogging. This is a replica of the xspy tool from forever ago.
When this lands I'll circle back around on adding the screenshot capability.
Verification
msfconsole