Skip to content

Commit 918fab2

Browse files
committed
1.5.0 new cli features and bug fixes
+ new root environment option (for Qegd and Dogd) + new default distro Boxs + better formatting for template + docker containers are now named (and can be made persistant)
1 parent 95d3813 commit 918fab2

File tree

11 files changed

+487
-415
lines changed

11 files changed

+487
-415
lines changed

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "vagd"
3-
version = "1.4.5"
3+
version = "1.5.0"
44
authors = [{ name = "0x6fe1be2" }]
55
description = "VirtuAlization GDb integrations in pwntools"
66
readme = "README.md"

src/vagd/box.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,19 @@ class Box:
1111
QEMU_FOCAL = "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
1212
QEMU_BIONIC = "https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img"
1313
QEMU_XENIAL = "https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img"
14+
QEMU_UBUNTU = QEMU_NOBLE
1415
QEMU_JAMMY_ARM = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-arm64.img"
1516

1617
DOCKER_NOBLE = "ubuntu:noble"
1718
DOCKER_JAMMY = "ubuntu:jammy"
1819
DOCKER_FOCAL = "ubuntu:focal"
1920
DOCKER_BIONIC = "ubuntu:bionic"
2021
DOCKER_XENIAL = "ubuntu:xenial"
22+
DOCKER_UBUNTU = DOCKER_NOBLE
23+
2124
DOCKER_I386_FOCAL = "i386/ubuntu:focal"
2225
DOCKER_I386_BIONIC = "i386/ubuntu:bionic"
2326
DOCKER_I386_XENIAL = "i386/ubuntu:xenial"
24-
DOCKER_ALPINE_316 = "alpine:3.16.6"
27+
28+
DOCKER_ALPINE_320 = "alpine:3.20"
29+
DOCKER_ALPINE = DOCKER_ALPINE_320

src/vagd/cli.py

+46-33
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
from vagd.virts.qegd import Qegd
1717
from vagd.virts.vagd import Vagd
1818

19-
DOGD_BOX = "Box.DOCKER_NOBLE"
19+
DOGD_BOX = "Box.DOCKER_UBUNTU"
2020
DOGD = "vm = Dogd(BINARY, image={box}, {args}) # Docker"
21-
QEGD_BOX = "Box.QEMU_NOBLE"
21+
QEGD_BOX = "Box.QEMU_UBUNTU"
2222
QEGD = "vm = Qegd(BINARY, img={box}, {args}) # Qemu"
2323
SHGD = (
2424
"vm = Shgd(BINARY, user='user', host='localhost', port=22, {args}) # SSH"
@@ -28,6 +28,11 @@
2828
VAGD_BOX = "Box.VAGRANT_JAMMY64"
2929
VAGD = "vm = Vagd(BINARY, {box}, {args}) # Vagrant"
3030

31+
ATAKA_ENV = """# ataka envs
32+
ATAKA = os.getenv('TARGET_IP') is not None
33+
IP = os.getenv('TARGET_IP', IP)
34+
EXTRA = json.loads(os.getenv('TARGET_EXTRA', '[]'))"""
35+
3136
app = typer.Typer(context_settings={"help_option_names": ["-h", "--help"]})
3237

3338
err_console = Console(stderr=True)
@@ -122,11 +127,13 @@ def template(
122127
ataka: Optional[bool] = typer.Option(
123128
False, "--ataka", help="create an ataka compatible template"
124129
),
130+
root: Optional[bool] = typer.Option(
131+
False, "--root", "-r", help="create a root environment"
132+
),
125133
):
126134
"""
127135
creates a template
128136
"""
129-
130137
if image != DOGD_BOX:
131138
dogd = True
132139
image = f"'{image}'"
@@ -140,7 +147,7 @@ def template(
140147
vbox = f"'{vbox}'"
141148

142149
templatePath = os.path.dirname(os.path.realpath(__file__))
143-
templateChunks = []
150+
templateChunks = list()
144151
aliasesPath = templatePath + "/res/aliases.txt"
145152
templatePath += "/res/template.txt"
146153
multi = False
@@ -160,6 +167,9 @@ def template(
160167
vms = []
161168
args = dict()
162169

170+
if root:
171+
args["user"] = "'root'"
172+
163173
if libs:
164174
args["libs"] = True
165175
if not libc:
@@ -168,6 +178,10 @@ def template(
168178
if files:
169179
args["files"] = "[" + ",".join(f"'{file}'" for file in files) + "]"
170180

181+
modules = list()
182+
if ataka:
183+
modules.append("json")
184+
171185
args["ex"] = "True"
172186
args["fast"] = "True"
173187

@@ -190,35 +204,34 @@ def template(
190204
else:
191205
templateChunks.append(line)
192206

193-
template = "".join(templateChunks).format(
194-
"{}",
195-
dependencies=", ".join(dependencies),
196-
aliases=aliases,
197-
binary=binary,
198-
ip=ip,
199-
port=str(port),
200-
env=env,
201-
ataka_env="# ataka envs\nIP = os.getenv('TARGET_IP', IP)\nEXTRA = json.loads(os.getenv('TARGET_EXTRA', '[]'))"
202-
if ataka
203-
else "",
204-
vms=("\n" + " " * 4).join(vms),
205-
libc=libc,
206-
aslr=aslr,
207-
is_local=True if local else "args.LOCAL",
208-
is_ataka=" or os.getenv('TARGET_IP')" if ataka else "",
209-
)
210-
211-
if output_exploit:
212-
output = "exploit.py"
213-
if output:
214-
with open(output, "w") as exploitFile:
215-
exploitFile.write(template)
216-
current_permissions = os.stat(output).st_mode
217-
new_permissions = current_permissions | (stat.S_IXUSR)
218-
os.chmod(output, new_permissions)
219-
else:
220-
syntax = Syntax(template, "python", theme="ansi_dark")
221-
console.print(syntax)
207+
template = "".join(templateChunks).format(
208+
"{}",
209+
modules="\n".join(f"import {module}" for module in modules),
210+
dependencies=", ".join(dependencies),
211+
aliases=aliases,
212+
binary=binary,
213+
ip=ip,
214+
port=str(port),
215+
env=env,
216+
ataka_env=ATAKA_ENV if ataka else "",
217+
vms=("\n" + " " * 4).join(vms),
218+
libc=libc,
219+
aslr=aslr,
220+
is_local=True if local else "args.LOCAL",
221+
is_ataka=" or ATAKA" if ataka else "",
222+
)
223+
224+
if output_exploit:
225+
output = "exploit.py"
226+
if output:
227+
with open(output, "w") as exploitFile:
228+
exploitFile.write(template)
229+
current_permissions = os.stat(output).st_mode
230+
new_permissions = current_permissions | (stat.S_IXUSR)
231+
os.chmod(output, new_permissions)
232+
else:
233+
syntax = Syntax(template, "python", theme="ansi_dark")
234+
console.print(syntax)
222235

223236

224237
@app.command()

src/vagd/res/aliases.txt

+27-21
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,47 @@
1+
# abbreviations
12
cst = constants
23
shc = shellcraft
34

4-
linfo = lambda x, *a: log.info(x, *a)
5-
lwarn = lambda x, *a: log.warn(x, *a)
5+
# logging
6+
linfo = lambda x, *a: log.info(x, *a)
7+
lwarn = lambda x, *a: log.warn(x, *a)
68
lerror = lambda x, *a: log.error(x, *a)
7-
lprog = lambda x, *a: log.progress(x, *a)
9+
lprog = lambda x, *a: log.progress(x, *a)
810

9-
byt = lambda x: x if isinstance(x, bytes) else x.encode() if isinstance(x, str) else repr(x).encode()
10-
phex = lambda x, y='leak': print('0x'+padhex(x, 16) + ' <- ' + y )
11-
lhex = lambda x, y='leak': linfo("0x%016x <- %s", x, y)
12-
pad = lambda x, s=8, v=b'\0', o='l': x.ljust(s, v) if o == 'l' else x.rjust(s, v)
11+
# type manipulation
12+
byt = lambda x: x if isinstance(x, bytes) else x.encode() if isinstance(x, str) else repr(x).encode()
13+
phex = lambda x, y='leak': print('0x'+padhex(x, 16) + ' <- ' + y )
14+
lhex = lambda x, y='leak': linfo("0x%016x <- %s", x, y)
15+
pad = lambda x, s=8, v=b'\0', o='l': x.ljust(s, v) if o == 'l' else x.rjust(s, v)
1316
padhex = lambda x, s=None: pad(hex(x)[2:],((x.bit_length()//8)+1)*2 if s is None else s, '0', 'r')
14-
upad = lambda x: u64(pad(x))
15-
tob = lambda x: bytes.fromhex(padhex(x))
17+
upad = lambda x: u64(pad(x))
18+
tob = lambda x: bytes.fromhex(padhex(x))
1619

20+
# elf aliases
1721
gelf = lambda elf=None: elf if elf else exe
18-
srh = lambda x, elf=None: gelf(elf).search(byt(x)).__next__()
22+
srh = lambda x, elf=None: gelf(elf).search(byt(x)).__next__()
1923
sasm = lambda x, elf=None: gelf(elf).search(asm(x), executable=True).__next__()
2024
lsrh = lambda x: srh(x, libc)
2125
lasm = lambda x: sasm(x, libc)
2226

27+
# cyclic aliases
2328
cyc = lambda x: cyclic(x)
2429
cfd = lambda x: cyclic_find(x)
2530
cto = lambda x: cyc(cfd(x))
2631

27-
t = None
28-
gt = lambda at=None: at if at else t
29-
sl = lambda x, t=None, *a, **kw: gt(t).sendline(byt(x), *a, **kw)
30-
se = lambda x, t=None, *a, **kw: gt(t).send(byt(x), *a, **kw)
31-
ss = lambda x, s, t=None, *a, **kw: sl(x, t, *a, **kw) if len(x) < s else lerror('ss to big: 0x%x > 0x%', len(x), s) if len(x) > s else se(x, *a, **kw)
32+
# tube aliases
33+
t = None
34+
gt = lambda at=None: at if at else t
35+
sl = lambda x, t=None, *a, **kw: gt(t).sendline(byt(x), *a, **kw)
36+
se = lambda x, t=None, *a, **kw: gt(t).send(byt(x), *a, **kw)
37+
ss = lambda x, s, t=None, *a, **kw: sl(x, t, *a, **kw) if len(x) < s else lerror('ss to big: 0x%x > 0x%x', len(x), s) if len(x) > s else se(x, *a, **kw)
3238
sla = lambda x, y, t=None, *a, **kw: gt(t).sendlineafter(byt(x), byt(y), *a, **kw)
33-
sa = lambda x, y, t=None, *a, **kw: gt(t).sendafter(byt(x), byt(y), *a, **kw)
39+
sa = lambda x, y, t=None, *a, **kw: gt(t).sendafter(byt(x), byt(y), *a, **kw)
3440
sas = lambda x, y, s, t=None, *a, **kw: sla(x, y, t, *a, **kw) if len(y) < s else lerror('sas to big: 0x%x > 0x%x', len(y), s) if len(y) > s else sa(x, y, *a, **kw)
35-
ra = lambda t=None, *a, **kw: gt(t).recvall(*a, **kw)
36-
rl = lambda t=None, *a, **kw: gt(t).recvline(*a, **kw)
41+
ra = lambda t=None, *a, **kw: gt(t).recvall(*a, **kw)
42+
rl = lambda t=None, *a, **kw: gt(t).recvline(*a, **kw)
3743
rls = lambda t=None, *a, **kw: rl(t=t, *a, **kw)[:-1]
3844
rcv = lambda x, t=None, *a, **kw: gt(t).recv(x, *a, **kw)
39-
ru = lambda x, t=None, *a, **kw: gt(t).recvuntil(byt(x), *a, **kw)
40-
it = lambda t=None, *a, **kw: gt(t).interactive(*a, **kw)
41-
cl = lambda t=None, *a, **kw: gt(t).close(*a, **kw)
45+
ru = lambda x, t=None, *a, **kw: gt(t).recvuntil(byt(x), *a, **kw)
46+
it = lambda t=None, *a, **kw: gt(t).interactive(*a, **kw)
47+
cl = lambda t=None, *a, **kw: gt(t).close(*a, **kw)

src/vagd/res/template.txt

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
#!/usr/bin/env python3
22
from pwn import *
3+
{modules}
34

4-
GDB_OFF = 0x555555554000
5-
IP = '{ip}'
6-
PORT = {port}
5+
GOFF = 0x555555554000
6+
IP = '{ip}'
7+
PORT = {port}
78
BINARY = '{binary}'
8-
ARGS = []
9-
ENV = {env} # os.environ
10-
GDB = f"""
9+
ARGS = []
10+
ENV = {env} # os.environ
11+
{ataka_env}
12+
GDB = f"""
1113
set follow-fork-mode parent
1214
1315
c"""
1416

1517
context.binary = exe = ELF(BINARY, checksec=False)
1618
context.aslr = {aslr}
1719

18-
{ataka_env}
19-
2020
{aliases}
2121

2222
def setup():

src/vagd/templates.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@
2222
# init user and ssh
2323
EXPOSE 22
2424
RUN useradd --create-home --shell /bin/bash -g sudo {user}
25-
RUN chown -R vagd:sudo /home/vagd
25+
RUN chown -R {user}:sudo /home/{user}
2626
RUN chmod u+s /usr/bin/sudo
27-
RUN echo "vagd ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/vagd && chmod 0440 /etc/sudoers.d/vagd
27+
RUN echo "{user} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/{user} && chmod 0440 /etc/sudoers.d/{user}
2828
USER {user}
2929
3030
WORKDIR /home/{user}
3131
COPY {keyfile} .ssh/authorized_keys
3232
3333
USER root
34+
COPY {keyfile} /root/.ssh/authorized_keys
3435
RUN mkdir -p /run/sshd && \\
3536
chmod 755 /run/sshd
3637
@@ -59,17 +60,18 @@
5960
6061
EXPOSE 22
6162
RUN chmod u+s /usr/bin/sudo
62-
RUN adduser -h /home/vagd -s /bin/ash -g sudo -D vagd
63-
RUN echo "vagd ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/vagd && chmod 0440 /etc/sudoers.d/vagd
64-
RUN echo "vagd:vagd" | chpasswd
63+
RUN adduser -h /home/{user} -s /bin/ash -g sudo -D {user}
64+
RUN echo "{user} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/{user} && chmod 0440 /etc/sudoers.d/{user}
65+
RUN echo "{user}:{user}" | chpasswd
6566
66-
USER vagd
67+
USER {user}
6768
68-
WORKDIR /home/vagd
69+
WORKDIR /home/{user}
6970
70-
COPY keyfile.pub .ssh/authorized_keys
71+
COPY {keyfile} .ssh/authorized_keys
7172
7273
USER root
74+
COPY {keyfile} /root/.ssh/authorized_keys
7375
RUN ssh-keygen -A
7476
RUN mkdir -p /run/sshd && \
7577
chmod 755 /run/sshd

0 commit comments

Comments
 (0)