Commit f317bc18 authored by PoroCYon's avatar PoroCYon Committed by PoroCYon
Browse files

USE_DT_DEBUG, SKIP_ENTRIES options

parent 9d117fe6
......@@ -9,11 +9,24 @@ PoC by Shiz, bugfixing and 64-bit version by PoroCYon.
```sh
./smol.py -lfoo -lbar input.o... smol-output.asm
nasm -I src/ [-DUSE_INTERP] [-DALIGN_STACK] [-DUSE_NX] [-DUSE_DL_FINI] \
-o nasm-output.o smol-output.asm
# -DALIGN_STACK: 64-bit only.
[-DUSE_DT_DEBUG] [-DSKIP_ENTRIES] -o nasm-output.o smol-output.asm
ld -T ld/link.ld -o binary nasm-output.o input.o...
```
* `USE_INTERP`: Include an interp segment in the output ELF file. If not, the
dynamic linker **must** be invoked *explicitely*! (You probably want to
enable this.)
* `ALIGN_STACK`: *64-bit only*: realign the stack so that SSE instructions
won't segfault.
* `USE_NX`: Don't use `RWE` segments at all. Not very well tested.
* `USE_DL_FINI`: keep track of the `_dl_fini` function and pass it to `_start`.
* `USE_DT_DEBUG`: retrieve the `struct link_map` from the `r_debug` linker
data (which is placed at `DT_DEBUG` at startup) instead of exploiting data
leakage from `_dt_start_user`. Might be more compatible, but strictly worse
size-wise on i386, and probably on x86_64 as well.
* `SKIP_ENTRIES`: skip the first two entries of the `struct link_map`, which
represent the main binary and the vDSO.
```
usage: smol.py [-h] [-m TARGET] [-l LIB] [-L DIR] [--nasm NASM] [--cc CC]
[--scanelf SCANELF] [--readelf READELF]
......
......@@ -28,6 +28,7 @@
%define PHDR_W (2)
%define PHDR_X (1)
%define DT_STRTAB (5)
%define DT_SYMTAB (6)
%define DT_STRTAB ( 5)
%define DT_SYMTAB ( 6)
%define DT_DEBUG (21)
#include<X11/X.h>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include <X11/Xatom.h>
#define CANVAS_WIDTH 400
#define CANVAS_HEIGHT ((CANVAS_WIDTH * 2)/3)
#define COLOR(r, g, b) ((r << 16) + (g << 8) + b)
#ifdef MAKE_ESC_WORK
static Atom wmDeleteMessage;
#endif
__attribute__((__used__))
void _start() {
//initialize the window
Display* dpy = XOpenDisplay(NULL);
//this is so the window isn't resizable
static XSizeHints hints = {
.flags = USPosition | PMinSize | PMaxSize,
.width = CANVAS_WIDTH, .height = CANVAS_HEIGHT,
.max_width = CANVAS_WIDTH, .max_height = CANVAS_HEIGHT,
.min_width = CANVAS_WIDTH, .min_height = CANVAS_HEIGHT,
};
//it seems like just keeping this as 0 is probs ok... lol
const int s = 0;//DefaultScreen(dpy);
Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, s), 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 0, 0, COLOR(89, 200, 243));
#ifdef MAKE_ESC_WORK
wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, win, &wmDeleteMessage, 1);
#endif
XSelectInput(dpy, win, ExposureMask|KeyPressMask);
XSetWMNormalHints(dpy, win, &hints);
//this actually opens the window
XMapWindow(dpy, win);
XEvent xev;
static XGCValues vals = {};
while(1/*XPending(dpy)>0*/) {
XNextEvent(dpy, &xev);
if (xev.type == Expose) {
GC gc = DefaultGC(dpy, s);
vals.foreground = COLOR(237, 165, 179);
XChangeGC(dpy, gc, GCForeground, &vals);
XFillRectangle(dpy, win, gc, 0, CANVAS_HEIGHT/5, CANVAS_WIDTH, CANVAS_HEIGHT * 3/5);
vals.foreground = COLOR(255, 255, 255);
XChangeGC(dpy, gc, GCForeground, &vals);
XFillRectangle(dpy, win, gc, 0, CANVAS_HEIGHT* 2/5, CANVAS_WIDTH, CANVAS_HEIGHT * 1/5);
}
#ifdef MAKE_ESC_WORK
else if (xev.type == KeyPress) {
if (((XKeyPressedEvent*)&xev)->keycode == XKeysymToKeycode(dpy,XK_Escape)) _exit(0);
} else if (xev.type == ClientMessage) {
if (xev.xclient.data.l[0] == wmDeleteMessage) _exit(0);
}
// swap buffers here
#endif
}
}
......@@ -82,6 +82,8 @@ header:
db "/lib/ld-linux.so.2",0
.interp.end:
%endif
global _DYNAMIC
_DYNAMIC:
.dynamic:
.dynamic.strtab:
dd DT_STRTAB ; d_tag
......@@ -90,4 +92,9 @@ header:
; this is required to be present or ld.so will crash, but it can be bogus
dd DT_SYMTAB ; d_tag: 6 = DT_SYMTAB
dd 0 ; d_un.d_ptr
%ifdef USE_DT_DEBUG
dd DT_DEBUG
_DEBUG:
dd 0
%endif
......@@ -92,6 +92,8 @@ interp:
interp.end:
%endif
global _DYNAMIC
_DYNAMIC:
dynamic:
dynamic.strtab:
dq DT_STRTAB ; d_tag
......@@ -99,4 +101,10 @@ dynamic.strtab:
dynamic.symtab:
dq DT_SYMTAB ; d_tag
dq 0 ; d_un.d_ptr
%ifdef USE_DT_DEBUG
dynamic.debug:
dq DT_DEBUG ; d_tag
_DEBUG:
dq 0 ; d_un.d_ptr
%endif
......@@ -17,6 +17,17 @@ _smol_start:
%endif
; try to get the 'version-agnostic' pffset of the stuff we're
; interested in
%ifdef USE_DT_DEBUG
mov eax, [rel _DEBUG]
mov eax, [eax + 4]
%endif
%ifdef SKIP_ENTRIES
mov eax, [eax + LM_NEXT_OFFSET] ; skip this binary
mov eax, [eax + LM_NEXT_OFFSET] ; skip the vdso
%endif
mov ebx, eax
mov esi, eax
.looper:
......
......@@ -24,11 +24,21 @@ _smol_start:
xchg r13, rdx ; _dl_fini
%endif
%ifdef USE_DT_DEBUG
mov r12, [rel _DEBUG]
mov r12, [r14 + 8]
%else
mov r12, [rsp - 8] ; return address of _dl_init
mov r11d, dword [r12 - 20] ; decode part of 'mov rdi, [rel _rtld_global]'
mov r12, [r12 + r11 - 16] ; ???
; struct link_map* root = r12
;mov r12, rdi
%endif
%ifdef SKIP_ENTRIES
mov r12, [r12 + L_NEXT_OFF] ; skip this binary
mov r12, [r12 + L_NEXT_OFF] ; skip the vdso
%endif
mov rsi, r12
; size_t* field = (size_t*)root;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment