first steps of exploration
This commit is contained in:
parent
3f6517aae2
commit
64f54c622d
@ -49,6 +49,8 @@ int bpf_lookup_elem(int fd, const void *key, void *value)
|
||||
return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
// TODO: add insert
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
|
@ -1,8 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/optimyze-interviews/OezguerKesim/GetRuntimeAddresses/ebpf"
|
||||
)
|
||||
@ -20,6 +25,41 @@ func main() {
|
||||
// Solution to your tasks goes here
|
||||
//
|
||||
|
||||
proc, err := os.Open("/proc")
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to open /proc: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
infos, err := proc.Readdir(-1)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to read /proc: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
proc.Close()
|
||||
|
||||
var (
|
||||
ownpid = os.Getpid()
|
||||
)
|
||||
|
||||
for _, pinfo := range infos {
|
||||
var pid_s = pinfo.Name()
|
||||
|
||||
// The entry /proc/NNN/ must be a directory with integer name
|
||||
if !pinfo.IsDir() {
|
||||
continue
|
||||
} else if pid, err := strconv.Atoi(pid_s); err != nil {
|
||||
continue
|
||||
} else if pid == ownpid { // skip our own pid
|
||||
continue
|
||||
} else if offset, found := searchSymbolIn(pid_s, "*python3*", "_PyRuntime"); !found {
|
||||
continue
|
||||
} else {
|
||||
fmt.Printf("going to set (%d -> 0x%x)\n\n", pid, offset)
|
||||
}
|
||||
}
|
||||
|
||||
mapContents, err := ebpf.GetMap(mapFD)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to get the map contents: %s", err)
|
||||
@ -32,3 +72,150 @@ func main() {
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
type region struct {
|
||||
start uint64 // could be uintptr
|
||||
end uint64
|
||||
}
|
||||
|
||||
func parseRegion(in string) (r region, e error) {
|
||||
parts := strings.Split(in, "-")
|
||||
|
||||
if len(parts) != 2 {
|
||||
e = fmt.Errorf("[parseRegion] unrecognized format for region: %#q", in)
|
||||
return
|
||||
}
|
||||
|
||||
r.start, e = strconv.ParseUint(parts[0], 16, 64)
|
||||
if e != nil {
|
||||
e = fmt.Errorf("[parseRegion] couldn't parse start-address %#q in %#q: %w", parts[0], in, e)
|
||||
return
|
||||
}
|
||||
|
||||
r.end, e = strconv.ParseUint(parts[1], 16, 64)
|
||||
if e != nil {
|
||||
e = fmt.Errorf("[parseRegion] couldn't parse end-address %#q in %#q: %w", parts[1], in, e)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func searchSymbolIn(pid, glob, symbol string) (offset uint64, ok bool) {
|
||||
// read the maps file for the binary and shared libraries
|
||||
path := filepath.Join("/proc", pid, "maps")
|
||||
maps, err := os.Open(path)
|
||||
if err != nil {
|
||||
// fmt.Printf("Warning: Failed to read %#q: %v\n", path, err)
|
||||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(maps)
|
||||
for scanner.Scan() {
|
||||
// address perms offset dev inode pathname
|
||||
// 7fdd8fece000-7fdd8ff74000 rw-p 00423000 fd:01 14156759 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
|
||||
fields := strings.Fields(scanner.Text())
|
||||
|
||||
// TODO: we assume that the pathname contains no spaces so
|
||||
// bytes.Fields splits the line excactly into six fields
|
||||
|
||||
if len(fields) != 6 {
|
||||
continue
|
||||
}
|
||||
|
||||
pathname := fields[5]
|
||||
|
||||
if !strings.HasPrefix(pathname, "/") { // Not a pathname
|
||||
continue
|
||||
}
|
||||
|
||||
filename := filepath.Base(pathname)
|
||||
ok, err := filepath.Match(glob, filename)
|
||||
if err != nil || !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if fields[1] != "rw-p" { // symbol needs to be writable
|
||||
continue
|
||||
}
|
||||
|
||||
sym, section, err := findSymbol("_PyRuntime", pathname)
|
||||
if err != nil || section == nil || sym == nil {
|
||||
// TODO: error handling
|
||||
// fmt.Printf("Warning: while reading mapped file %q: %w", pathname, err)
|
||||
continue
|
||||
}
|
||||
|
||||
arange, err := parseRegion(fields[0])
|
||||
if err != nil {
|
||||
fmt.Printf("%w\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
fileoffset, err := strconv.ParseUint(fields[2], 16, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("Error while parsing fileoffset %#q: %w\n", fields[2], err)
|
||||
continue
|
||||
}
|
||||
|
||||
memoff := sym.Value - section.Addr + alignedOffset(section)
|
||||
|
||||
fmt.Printf("pid: %s\nsym: %#v\nsection: %#v\nmemoff: 0x%x\narange: %#v\nmap-fileoffset: 0x%x\npathname: %s\n", pid, sym, section, memoff, arange, fileoffset, pathname)
|
||||
|
||||
// stop when only _one_ is found
|
||||
return arange.start + memoff - fileoffset, true
|
||||
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func findSymbol(symbol string, pathname string) (*elf.Symbol, *elf.SectionHeader, error) {
|
||||
// TODO: caching
|
||||
|
||||
var (
|
||||
sym *elf.Symbol
|
||||
section *elf.Section
|
||||
header *elf.SectionHeader
|
||||
)
|
||||
|
||||
file, err := elf.Open(pathname)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
symbols, err := file.DynamicSymbols()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, s := range symbols {
|
||||
if s.Name == symbol {
|
||||
sym = &s
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if sym == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
if len(file.Sections) < int(sym.Section) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
section = file.Sections[sym.Section]
|
||||
if section == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
header = §ion.SectionHeader
|
||||
|
||||
return sym, header, nil
|
||||
}
|
||||
|
||||
func alignedOffset(section *elf.SectionHeader) uint64 {
|
||||
mask := section.Addralign - 1
|
||||
return (section.Offset + mask) & (^mask)
|
||||
}
|
||||
|
44
TODO.md
Normal file
44
TODO.md
Normal file
@ -0,0 +1,44 @@
|
||||
# TODO
|
||||
|
||||
From map proc(5):
|
||||
|
||||
```
|
||||
/proc/[pid]/maps
|
||||
A file containing the currently mapped memory regions and their access permissions. See mmap(2) for some further information about memory
|
||||
mappings.
|
||||
|
||||
Permission to access this file is governed by a ptrace access mode PTRACE_MODE_READ_FSCREDS check; see ptrace(2).
|
||||
|
||||
The format of the file is:
|
||||
|
||||
address perms offset dev inode pathname
|
||||
00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon
|
||||
00651000-00652000 r--p 00051000 08:02 173521 /usr/bin/dbus-daemon
|
||||
00652000-00655000 rw-p 00052000 08:02 173521 /usr/bin/dbus-daemon
|
||||
00e03000-00e24000 rw-p 00000000 00:00 0 [heap]
|
||||
00e24000-011f7000 rw-p 00000000 00:00 0 [heap]
|
||||
...
|
||||
35b1800000-35b1820000 r-xp 00000000 08:02 135522 /usr/lib64/ld-2.15.so
|
||||
35b1a1f000-35b1a20000 r--p 0001f000 08:02 135522 /usr/lib64/ld-2.15.so
|
||||
35b1a20000-35b1a21000 rw-p 00020000 08:02 135522 /usr/lib64/ld-2.15.so
|
||||
35b1a21000-35b1a22000 rw-p 00000000 00:00 0
|
||||
35b1c00000-35b1dac000 r-xp 00000000 08:02 135870 /usr/lib64/libc-2.15.so
|
||||
35b1dac000-35b1fac000 ---p 001ac000 08:02 135870 /usr/lib64/libc-2.15.so
|
||||
35b1fac000-35b1fb0000 r--p 001ac000 08:02 135870 /usr/lib64/libc-2.15.so
|
||||
35b1fb0000-35b1fb2000 rw-p 001b0000 08:02 135870 /usr/lib64/libc-2.15.so
|
||||
...
|
||||
f2c6ff8c000-7f2c7078c000 rw-p 00000000 00:00 0 [stack:986]
|
||||
...
|
||||
7fffb2c0d000-7fffb2c2e000 rw-p 00000000 00:00 0 [stack]
|
||||
7fffb2d48000-7fffb2d49000 r-xp 00000000 00:00 0 [vdso]
|
||||
|
||||
```
|
||||
|
||||
1. read file(s) as elf
|
||||
2. extract offset(s) of symbol(s)
|
||||
3. find procs with mappings of those files
|
||||
4. check if symbol-offset falls into any (address-range, offset) of such a mapping
|
||||
5. if so, populate the ebpf map
|
||||
|
||||
Optional:
|
||||
6. trigger, if file is read/mapped?
|
69
scratchpad.txt
Normal file
69
scratchpad.txt
Normal file
@ -0,0 +1,69 @@
|
||||
gdb sagt: 0x8de5c0
|
||||
|
||||
DYNAMIC 0x0000000000437dc0
|
||||
|
||||
|
||||
|
||||
1464: 00000000008de5c0 1520 OBJECT GLOBAL DEFAULT 24 _PyRuntime
|
||||
|
||||
|
||||
no. 1464 -> 1464*24 = 35136 = 0x 8940
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Programm-Header:
|
||||
Typ Offset VirtAdr PhysAdr
|
||||
DateiGr SpeiGr Flags Ausr.
|
||||
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
|
||||
0x0000000000000268 0x0000000000000268 R 0x8
|
||||
INTERP 0x00000000000002a8 0x00000000004002a8 0x00000000004002a8
|
||||
0x000000000000001c 0x000000000000001c R 0x1
|
||||
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
|
||||
0x0000000000020ad0 0x0000000000020ad0 R 0x1000
|
||||
LOAD 0x0000000000021000 0x0000000000421000 0x0000000000421000
|
||||
0x0000000000258515 0x0000000000258515 R E 0x1000
|
||||
LOAD 0x000000000027a000 0x000000000067a000 0x000000000067a000
|
||||
0x00000000001bd120 0x00000000001bd120 R 0x1000
|
||||
LOAD 0x0000000000437db0 0x0000000000838db0 0x0000000000838db0
|
||||
0x00000000000a56a0 0x00000000000c8c70 RW 0x1000
|
||||
DYNAMIC 0x0000000000437dc0 0x0000000000838dc0 0x0000000000838dc0
|
||||
0x0000000000000230 0x0000000000000230 RW 0x8
|
||||
|
||||
|
||||
|
||||
1464: 00000000008de5c0 1520 OBJECT GLOBAL DEFAULT 24 _PyRuntime
|
||||
|
||||
|
||||
00000000008de5c0 - 0x0000000000838dc0 = A5800
|
||||
|
||||
4DE5C0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
018880
|
||||
|
||||
|
||||
00000000004c9b20
|
||||
|
||||
|
||||
8De5C0
|
||||
|
||||
838DC0
|
||||
|
||||
A4800
|
||||
|
||||
|
||||
gdb sagt 0x8de5c0 zu python3.7
|
||||
|
||||
gdb sagt 7FDD8FF73B20 zu /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
|
||||
7FDD8FAAA000-7FDD8FB16000 r--p 00000000 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
7FDD8FB16000-7FDD8FD2B000 r-xp 0006c000 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
7FDD8FD2B000-7FDD8FEC9000 r--p 00281000 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
7FDD8FEC9000-7FDD8FECA000 ---p 0041f000 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
7FDD8FECA000-7FDD8FECE000 r--p 0041f000 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
||||
7FDD8FECE000-7FDD8FF74000 rw-p 00423000 /usr/lib/x86_64-linux-gnu/libpython3.7m.so.1.0
|
Loading…
Reference in New Issue
Block a user