Works both with Python 2.7 and Python 3.X on Linux and Windows. Technically it's a snippet from my ReRe CTF challenge (RE 500) published (with sources) on my blog.
import time
import math
import ctypes
import os
import hashlib
import sys
import colorsys
WINNT = os.name == 'nt'
def InitStuff():
# Linux-only stuff.
if not WINNT:
# TermIOs library.
global termios
import termios
# Select library.
global select
import select
# fcntl and ioctl stuff.
global fcntl
import fcntl
# Your favorite structure module.
global struct
import struct
# And now for some Windows-only stuff.
if WINNT:
# kernel32.dll handle.
global K32, CRT
K32 = ctypes.windll.kernel32
CRT = ctypes.cdll.msvcrt
# Active Console Screen Buffer and Active Console Input Buffer
global ACSB, ACIB, STD_OUTPUT_HANDLE, STD_INPUT_HANDLE
STD_OUTPUT_HANDLE = -11
STD_INPUT_HANDLE = -10
ACSB = K32.GetStdHandle(STD_OUTPUT_HANDLE)
ACIB = K32.GetStdHandle(STD_INPUT_HANDLE)
# CONSOLE_CURSOR_INFO used to hide the cursor.
global CONSOLE_CURSOR_INFO
class CONSOLE_CURSOR_INFO(ctypes.Structure):
_fields_ = [
("dwSize", ctypes.c_uint),
("bVisible", ctypes.c_int) # Uhm, yes, BOOL == int.
]
def ChangeConsoleMode_Windows(add, chmode):
mode = ctypes.c_uint()
K32.GetConsoleMode(ACIB, ctypes.byref(mode))
if add:
mode.value |= chmode
else:
mode.value &= (~chmode) & 0xffffffff
K32.SetConsoleMode(ACIB, mode)
def ChangeConsoleMode_Linux(add, idx, chmode):
mode = termios.tcgetattr(0) # STDIN
if add:
mode[idx] |= chmode
else:
mode[idx] &= (~chmode) & 0xffffffff
termios.tcsetattr(0, termios.TCSADRAIN, mode)
def ChangeBuffering(on):
if not WINNT:
ChangeConsoleMode_Linux(on, 3, termios.ICANON)
return
# ENABLE_LINE_INPUT 0x0002
ChangeConsoleMode_Windows(on, 2)
def ChangeEcho(show):
if not WINNT:
ChangeConsoleMode_Linux(show, 3, termios.ECHO)
return
# ENABLE_ECHO_INPUT 0x0004
ChangeConsoleMode_Windows(show, 4)
def ChangeCursor(show):
if not WINNT:
sys.stdout.write([
"\x1b[?25l",
"\x1b[?25h"
][show])
sys.stdout.flush()
return
if not show:
ChangeCursor.arch = CONSOLE_CURSOR_INFO()
K32.GetConsoleCursorInfo(ACSB, ctypes.byref(ChangeCursor.arch))
new_info = CONSOLE_CURSOR_INFO(0, 0)
K32.SetConsoleCursorPosition(ACSB, ctypes.byref(new_info))
return
# Show.
K32.SetConsoleCursorPosition(ACSB, ctypes.byref(ChangeCursor.arch))
def MaybeGetChar():
if not WINNT:
dr, dw, de = select.select([sys.stdin], [], [], 0)
if not dr:
return None
return sys.stdin.read(1)
if CRT._kbhit():
return chr(CRT._getch())
return None
InitStuff()
try:
ChangeCursor(show=False)
ChangeBuffering(on=False)
ChangeEcho(show=False)
input = ""
while True:
ch = MaybeGetChar()
if ch is None:
time.sleep(0.01)
else:
print ("YOU PRESSED: " + repr(ch) + " " + str(ord(ch)))
except KeyboardInterrupt:
ChangeEcho(show=True)
ChangeBuffering(on=True)
ChangeCursor(show=True)
|