-
Notifications
You must be signed in to change notification settings - Fork 1
/
ldcp.py
executable file
·93 lines (71 loc) · 2.38 KB
/
ldcp.py
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
#!/usr/bin/env python
import argparse
import os
import shutil
import subprocess
LDLINUX = {
'elf32-i386': 'ld-linux.so.2',
'elf64-x86-64': 'ld-linux-x86-64.so.2'
}
def collect(roots):
paths = {}
def recur(path):
filename = os.path.basename(path)
if filename in paths:
return
paths[filename] = path
try:
out = subprocess.check_output(['ldd', path]).decode('UTF-8')
except subprocess.CalledProcessError:
return
for line in out.splitlines():
args = line.split()
if 'linux-vdso.so.1' in args or 'linux-gate.so.1' in args or 'statically' in args:
continue
if '=>' in args:
pos = args.index('=>')
arg = args[pos + 1]
recur(arg)
recur(args[0])
for root in roots:
recur(root)
return paths
def save(paths, dst):
if not os.path.exists(dst):
os.makedirs(dst)
for filename, path in paths.items():
dstpath = os.path.join(dst, filename)
if not os.path.exists(dstpath) or not os.path.samefile(path, dstpath):
shutil.copy(path, dstpath)
os.chmod(dstpath, 0o755)
if filename in LDLINUX.values():
continue
try:
headers = subprocess.check_output(['objdump', '-h', dstpath]).decode('UTF-8').split()
except subprocess.CalledProcessError:
continue
if 'format' not in headers[:-1]:
continue
ldlinux = LDLINUX[headers[headers.index('format') + 1]]
args = ['patchelf', '--set-rpath', '$ORIGIN']
if '.interp' in headers:
args += ['--set-interpreter', './' + ldlinux]
subprocess.check_call(args + [dstpath])
if '.so' not in filename:
os.rename(dstpath, dstpath + '.bin')
with open(dstpath, 'w') as f:
f.write('#!/bin/sh\n')
f.write('d="$(dirname "$(readlink -f "$0")")"\n')
f.write('exec "$d/{}" "$d/{}" "$@"\n'.format(ldlinux, filename + '.bin'))
os.chmod(dstpath, 0o755)
def main():
os.environ['LANG'] = 'C'
parser = argparse.ArgumentParser()
arg = parser.add_argument
arg('dst')
arg('path', nargs='+')
args = parser.parse_args()
paths = collect(args.path)
save(paths, args.dst)
if __name__ == '__main__':
main()