Skip to content

Commit b29c0b9

Browse files
committed
1.4.0 Dogd upgrade and config changes
+ ~/.vagd was moved to ~/.local/share/vagd + Dogd now supports Entrypoint overwrite + improved Dogd chaching (for symbols) + update template to improve --libs
1 parent 4db12c4 commit b29c0b9

File tree

10 files changed

+63
-51
lines changed

10 files changed

+63
-51
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
venv
2+
env
23
.idea
34
.vagrant
45
Vagrantfile
@@ -11,3 +12,6 @@ sysroot/
1112
.vagd
1213
__pycache__/
1314
_build
15+
test/exploit.py
16+
test/flag
17+
test/libs

README.md

+8-22
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,22 @@
44

55
VirtuAlization GDb integrations in pwntools
66

7-
8-
97
## Installation
108

119
```bash
1210
pip install vagd
1311
```
12+
1413
or from repo with
14+
1515
```bash
1616
git clone https://github.com/gfelber/vagd
1717
pip install ./vagd/
1818
```
1919

20-
21-
2220
## Usage
2321

24-
+ `vagd template [OPTIONS] [BINARY] [IP] [PORT]` to generate a template, list OPTIONS with help `-h`
22+
- `vagd template [OPTIONS] [BINARY] [IP] [PORT]` to generate a template, list OPTIONS with help `-h`
2523

2624
```python
2725
#!/usr/bin/env python
@@ -30,7 +28,7 @@ from pwn import *
3028
IP = '' # remote IP
3129
PORT = 0 # remote PORT
3230
BINARY = '' # PATH to local binary e.g. ./chal
33-
ARGS = [] # ARGS supplied to binary
31+
ARGS = [] # ARGS supplied to binary
3432
ENV = {} # ENVs supplied to binary
3533
# GDB SCRIPT, executed at start of GDB session (set breakpoint here)
3634
GDB = f"""
@@ -51,7 +49,7 @@ def get_target(**kw):
5149

5250
from vagd import Dogd, Qegd, Shgd
5351
if not vm:
54-
# Docker
52+
# Docker
5553
vm = Dogd(exe.path, image="ubuntu:jammy", ex=True, fast=True)
5654
# or Qemu
5755
vm = Qegd(exe.path, img="https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img", ex=True, fast=True)
@@ -65,7 +63,7 @@ t = get_target()
6563
t.interactive()
6664
```
6765

68-
+ `vagd info BINARY` to print info about binary
66+
- `vagd info BINARY` to print info about binary
6967

7068
```bash
7169
# run as process in VM
@@ -78,13 +76,9 @@ t.interactive()
7876

7977
I recommend using [pwndbg](https://github.com/pwndbg/pwndbg).
8078

81-
82-
8379
## Files
8480

85-
All created files ares stored in the local `./.vagd/` directory. Additional large files (e.g. cloudimages) are stored in the home directory `~/.vagd/` or handled by tools themselfs (e.g. Docker).
86-
87-
81+
All created files ares stored in the local `./.vagd/` directory. Additional large files (e.g. cloudimages) are stored in the home directory `~/.share/local/vagd/` or handled by tools themselfs (e.g. Docker).
8882

8983
## CLI
9084

@@ -105,20 +99,14 @@ vagd scp [OPTIONS] SOURCE [TARGET]
10599
vagd clean [OPTIONS]
106100
```
107101

108-
109-
110102
## [Documentation](https://vagd.gfelber.dev)
111103

112-
113-
114104
## Boxes
115105

116106
A listed of known working Boxes can be found in the [Documentation](http://vagd.gfelber.dev/autoapi/vagd/box/index.html#module-vagd.box).
117107
Other images might also work but currently only distributions that use `apt` and alpine for Docker are supported.
118108
This limitation may be circumvented by creating a target yourself (with the dependencies gdbserver, python, openssh) and creating a ssh connection via Shgd.
119109

120-
121-
122110
## Troubleshooting
123111

124112
### background processes
@@ -135,9 +123,7 @@ files on the virtual instance are never overwritten this has performance reason
135123

136124
### gdb performance
137125

138-
Using gdbserver and gdb to index libraries can be very slow. Therefore an experimental feature is available that mounts libraries locally: `Dogd(..., ex=True, fast=True)`
139-
140-
126+
Using gdbserver and gdb to index libraries can be very slow. Therefore an experimental feature is available that mounts libraries locally: `Dogd(..., ex=True, fast=True)`
141127

142128
## Future plans
143129

pyproject.toml

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

src/vagd/cli.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -109,24 +109,26 @@ def template(
109109
aliasesPath = templatePath + "/res/aliases.txt"
110110
templatePath += '/res/template.txt'
111111
multi = False
112+
112113
if not any((dogd, qegd, vagd, shgd)):
113114
dogd = qegd = True
114115

115116
if sum((dogd, qegd, vagd, shgd)) > 1:
116117
multi = True
117118

118-
119119
env = {}
120+
120121
if libc:
121122
files.append(libc)
122-
env['LD_PRELOAD'] = os.path.basename(libc)
123123

124124
dependencies = []
125125
vms = []
126126
args = dict()
127127

128128
if libs:
129129
args['libs'] = True
130+
if not libc:
131+
libc = './libs/libc.so.6'
130132

131133
if files:
132134
args['files'] = '[' + ','.join(f"'{file}'" for file in files) + ']'
@@ -146,14 +148,10 @@ def template(
146148
with open(aliasesPath, 'r') as aliases_file:
147149
aliases = aliases_file.read()
148150

149-
150-
if libc and libs:
151-
err_console.print("using --libs and --libc, uncomment libc after init")
152-
153151
with (open(templatePath, 'r') as templateFile):
154152
for line in templateFile.readlines():
155153

156-
if libc and not libs and line.startswith('# libc'):
154+
if libc and line.startswith('# libc'):
157155
templateChunks.append(line[2:])
158156
else:
159157
templateChunks.append(line)

src/vagd/res/template.txt

+18-11
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,27 @@ set follow-fork-mode parent
1313
c"""
1414

1515
context.binary = exe = ELF(BINARY, checksec=False)
16-
# libc = ELF('{libc}', checksec=False)
1716
context.aslr = {aslr}
1817

1918
{aliases}
2019

21-
vm = None
22-
def get_target(**kw) -> tubes.tube:
20+
def setup():
2321
global vm
22+
if args.REMOTE or {is_local}:
23+
return
24+
25+
try:
26+
from vagd import {dependencies}, Box # only load vagd if needed
27+
except:
28+
log.error("Failed to import vagd, either run locally using LOCAL or install it")
29+
if not vm:
30+
{vms}
31+
if vm.is_new:
32+
log.info("new vagd instance") # additional setup here
33+
2434

35+
vm = None
36+
def get_target(**kw) -> tubes.tube:
2537
if args.REMOTE:
2638
# context.log_level = 'debug'
2739
return remote(IP, PORT)
@@ -31,16 +43,11 @@ def get_target(**kw) -> tubes.tube:
3143
return gdb.debug([BINARY] + ARGS, env=ENV, gdbscript=GDB, **kw)
3244
return process([BINARY] + ARGS, env=ENV, **kw)
3345

34-
try:
35-
from vagd import {dependencies}, Box # only load vagd if needed
36-
except:
37-
log.error("Failed to import vagd, either run locally using LOCAL or install it")
38-
if not vm:
39-
{vms}
40-
if vm.is_new:
41-
log.info("new vagd instance") # additional setup here
4246
return vm.start(argv=ARGS, env=ENV, gdbscript=GDB, **kw)
4347

48+
setup()
49+
50+
# libc = ELF('{libc}', checksec=False)
4451

4552
t = get_target()
4653

src/vagd/templates.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111

1212
DOCKER_TEMPLATE = '''FROM {image}
1313
14+
USER root
15+
1416
# install packages
15-
RUN apt-get update && \\
16-
NEEDRESTART_MODE=a apt-get install -y {packages}
17+
ENV DEBIAN_FRONTEND=noninteractive
18+
RUN apt-get update
19+
RUN apt-get install -y {packages}
1720
1821
# init user and ssh
1922
EXPOSE 22
@@ -29,15 +32,18 @@
2932
USER root
3033
RUN mkdir -p /run/sshd && \\
3134
chmod 755 /run/sshd
32-
33-
35+
36+
ENTRYPOINT []
37+
3438
CMD /usr/sbin/sshd; \\
3539
while true; do sleep 1m; done
3640
'''
3741

3842
# TODO: proper template generation for alpine
3943
DOCKER_ALPINE_TEMPLATE = '''FROM {image}
4044
45+
USER root
46+
4147
# install packages
4248
RUN apk update
4349
RUN apk add --no-cache python3
@@ -66,6 +72,7 @@
6672
RUN mkdir -p /run/sshd && \
6773
chmod 755 /run/sshd
6874
75+
ENTRYPOINT []
6976
7077
CMD /usr/sbin/sshd; \
7178
while true; do sleep 1m; done

src/vagd/virts/dogd.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Dogd(Shgd):
2929
3030
vagd ssh
3131
# or
32-
ssh -o "StrictHostKeyChecking=no" -i ~/.vagd/keyfile -p $(cut .vagd/docker.lock -d":" -f 2) vagd@0.0.0.0
32+
ssh -o "StrictHostKeyChecking=no" -i ~/.share/local/vagd/keyfile -p $(cut .vagd/docker.lock -d":" -f 2) vagd@0.0.0.0
3333
3434
| connect with docker exec
3535
@@ -47,7 +47,7 @@ class Dogd(Shgd):
4747
4848
| Docker containers are automatically removed after they stop
4949
| Docker images need to be manually removed from docker
50-
| Dockerfiles are stored in home directory to allow caching ~/.vagd/docker/<image>/Dockerfile
50+
| Dockerfiles are stored in home directory to allow caching ~/.share/local/vagd/docker/<image>/Dockerfile
5151
5252
.. code-block:: bash
5353
@@ -67,6 +67,7 @@ class Dogd(Shgd):
6767
_gdbsrvport: int
6868
_ex: bool
6969
_forward: Dict[str, int]
70+
_symbols: bool
7071

7172
TYPE = 'dogd'
7273
DOCKERHOME = Pwngd.HOME_DIR + "docker/"
@@ -117,12 +118,19 @@ def _build_image(self):
117118
helper.info('building docker image')
118119
hash = self._image.find('@')
119120
if hash != -1:
120-
tag = self._image[:hash]
121+
tag = self._image[:hash].replace(':', '_')
121122
# add first 8 characters of hash
122123
tag += self._image[self._image.rfind(':'):][:8]
123124
else:
124125
tag = self._image
125126

127+
if self._symbols:
128+
if ':' not in tag:
129+
tag += ':'
130+
else:
131+
tag += '_'
132+
tag += 'symbols'
133+
126134
return self._client.images.build(path=os.path.dirname(self._dockerfile), tag=f'vagd/{tag}')[0]
127135

128136
def _vm_create(self):
@@ -206,6 +214,7 @@ def __init__(self,
206214
self._user = user
207215
self._forward = forward
208216
self._ex = ex
217+
self._symbols = symbols
209218
if self._isalpine and not self._ex:
210219
helper.error("Docker alpine images requires experimental features")
211220
if self._forward is None:

src/vagd/virts/pwngd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Pwngd(ABC):
2727
:param ex: if experimental features should be enabled
2828
"""
2929
LOCAL_DIR = './.vagd/'
30-
HOME_DIR = os.path.expanduser('~/.vagd/')
30+
HOME_DIR = os.path.expanduser('~/.local/share/vagd/')
3131
SYSROOT = LOCAL_DIR + 'sysroot/'
3232
LOCKFILE = LOCAL_DIR + 'vagd.lock'
3333
SYSROOT_LIB = SYSROOT + 'lib/'

src/vagd/virts/qegd.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Qegd(Shgd):
3838
3939
vagd ssh
4040
# or
41-
ssh -o "StrictHostKeyChecking=no" -i ~/.vagd/keyfile -p $(cat .vagd/qemu.lock) ubuntu@0.0.0.0
41+
ssh -o "StrictHostKeyChecking=no" -i ~/.share/local/vagd/keyfile -p $(cat .vagd/qemu.lock) ubuntu@0.0.0.0
4242
4343
| Kill from cmd:
4444
@@ -48,7 +48,7 @@ class Qegd(Shgd):
4848
# or
4949
kill $(pgrep qemu)
5050
51-
| Qemu images are cached in the home directory: :code:`~/.vagd/qemu-imgs/`
51+
| Qemu images are cached in the home directory: :code:`~/.share/local/vagd/qemu-imgs/`
5252
|
5353
| current used images are stored in the local directory: :code:`./.vagd/current.img`
5454
| These should be deleted automatically, but if a machine gets improperly stopped

test/vagd

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../src/vagd

0 commit comments

Comments
 (0)