summaryrefslogtreecommitdiff
path: root/other/reducebind
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /other/reducebind
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/reducebind')
-rw-r--r--other/reducebind/pcdump.c186
-rw-r--r--other/reducebind/ptrace-legit.c137
-rwxr-xr-xother/reducebind/reducebindbin0 -> 9360 bytes
-rw-r--r--other/reducebind/reducebind.c311
4 files changed, 634 insertions, 0 deletions
diff --git a/other/reducebind/pcdump.c b/other/reducebind/pcdump.c
new file mode 100644
index 0000000..7072576
--- /dev/null
+++ b/other/reducebind/pcdump.c
@@ -0,0 +1,186 @@
1/* memory dump utility
2 * -scut
3 */
4
5#include <sys/types.h>
6#include <sys/ptrace.h>
7#include <sys/wait.h>
8#include <sys/user.h>
9#include <errno.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <libgen.h> /* basename */
14
15
16void dr_dump (FILE *out, struct user *child);
17void hexdump (unsigned char *data, unsigned int amount);
18
19
20int
21main (int argc, char *argv[], char *envp[])
22{
23 pid_t fpid; /* child pid, gets ptraced */
24 char * argv0;
25 struct user regs; /* PTRACE pulled registers */
26 unsigned long int addr, /* segment start address */
27 addr_end, /* segment end address */
28 len; /* length of segment */
29 unsigned long int addr_walker, /* walker to dump memory */
30 eip; /* current childs eip */
31
32 /* array to temporarily store data into */
33 unsigned char data_saved[sizeof (unsigned long int)];
34
35 /* file to read mapping information */
36 FILE * map_f; /* /proc/<pid>/maps stream */
37 unsigned char map_line[256]; /* one line each from map */
38
39 /* data for the dump files */
40 FILE * dump_f; /* stream */
41 char dump_name[64]; /* filename buffer */
42
43
44 if (argc < 2) {
45 printf ("usage: %s <argv0 [argv1 [...]]>\n\n", argv[0]);
46 printf ("will run 'argv0' as program with given arguments.\n\n");
47
48 exit (EXIT_FAILURE);
49 }
50
51 fpid = fork ();
52 if (fpid < 0) {
53 perror ("fork");
54 exit (EXIT_FAILURE);
55 }
56 if (fpid == 0) { /* child */
57 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
58 perror ("ptrace PTRACE_TRACEME");
59 exit (EXIT_FAILURE);
60 }
61 fprintf (stderr, " child: TRACEME set\n");
62
63 fprintf (stderr, " child: executing: %s\n", argv[2]);
64 close (1);
65 dup2 (2, 1);
66 execve (argv[1], &argv[1], envp);
67
68 /* failed ? */
69 perror ("execve");
70 exit (EXIT_FAILURE);
71 }
72
73 wait (NULL);
74
75 memset (&regs, 0, sizeof (regs));
76
77 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
78 perror ("ptrace PTRACE_GETREGS");
79 exit (EXIT_FAILURE);
80 }
81 fprintf (stderr, "[0x%08lx] first stop\n", regs.regs.eip);
82 dr_dump (stderr, &regs);
83
84 regs.u_debugreg[0] = 0x41414141;
85 if (ptrace (PTRACE_SETREGS, fpid, NULL, &regs) < 0) {
86 perror ("ptrace PTRACE_GETREGS");
87 exit (EXIT_FAILURE);
88 }
89 sleep (10);
90 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
91 perror ("ptrace PTRACE_GETREGS");
92 exit (EXIT_FAILURE);
93 }
94 fprintf (stderr, "[0x%08lx] first stop\n", regs.regs.eip);
95 dr_dump (stderr, &regs);
96
97 /* now single step until given eip is reached */
98 do {
99 sleep (1);
100
101 if (ptrace (PTRACE_SYSCALL, fpid, NULL, NULL) < 0) {
102 perror ("ptrace PTRACE_SINGLESTEP");
103 exit (EXIT_FAILURE);
104 }
105 wait (NULL);
106
107 memset (&regs, 0, sizeof (regs));
108 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
109 perror ("ptrace PTRACE_GETREGS");
110 exit (EXIT_FAILURE);
111 }
112 fprintf (stderr, "0x%08lx\n", regs.regs.eip);
113 dr_dump (stderr, &regs);
114 } while (1);
115
116 if (ptrace (PTRACE_DETACH, fpid, NULL, NULL) < 0) {
117 perror ("ptrace PTRACE_DETACH");
118 exit (EXIT_FAILURE);
119 }
120
121 fprintf (stderr, "MEMDUMP: success. terminating.\n");
122 exit (EXIT_SUCCESS);
123}
124
125
126
127void
128hexdump (unsigned char *data, unsigned int amount)
129{
130 unsigned int dp, p; /* data pointer */
131 const char trans[] =
132 "................................ !\"#$%&'()*+,-./0123456789"
133 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
134 "nopqrstuvwxyz{|}~...................................."
135 "....................................................."
136 "........................................";
137
138 for (dp = 1; dp <= amount; dp++) {
139 printf ("%02x ", data[dp-1]);
140 if ((dp % 8) == 0)
141 printf (" ");
142 if ((dp % 16) == 0) {
143 printf ("| ");
144 p = dp;
145 for (dp -= 16; dp < p; dp++)
146 printf ("%c", trans[data[dp]]);
147 printf ("\n");
148 }
149 }
150 if ((amount % 16) != 0) {
151 p = dp = 16 - (amount % 16);
152 for (dp = p; dp > 0; dp--) {
153 printf (" ");
154 if (((dp % 8) == 0) && (p != 8))
155 printf (" ");
156 }
157 printf (" | ");
158 for (dp = (amount - (16 - p)); dp < amount; dp++)
159 printf ("%c", trans[data[dp]]);
160 }
161 printf ("\n");
162
163 return;
164}
165
166
167void
168dr_dump (FILE *out, struct user *child)
169{
170 char * desc[] = { "dr0 (debug address register)",
171 "dr1 (debug address register)",
172 "dr2 (debug address register)",
173 "dr3 (debug address register)",
174 "dr4 (reserved)",
175 "dr5 (reserved)",
176 "dr6 (debug status register)",
177 "dr7 (debug control register)" };
178 int n;
179
180 for (n = 0 ; n < 8 ; ++n) {
181 fprintf (out, "\t0x%08lx %s\n", child->u_debugreg[n],
182 desc[n]);
183 }
184}
185
186
diff --git a/other/reducebind/ptrace-legit.c b/other/reducebind/ptrace-legit.c
new file mode 100644
index 0000000..da93830
--- /dev/null
+++ b/other/reducebind/ptrace-legit.c
@@ -0,0 +1,137 @@
1
2#include <sys/types.h>
3#include <sys/ptrace.h>
4#include <sys/wait.h>
5#include <sys/user.h>
6#include <unistd.h>
7#include <stdlib.h>
8#include <stdio.h>
9
10void
11hexdump (unsigned char *data, unsigned int amount);
12
13unsigned char shellcode[] = "\x90\x90\xcc\x73";
14
15int
16main (int argc, char *argv[])
17{
18 pid_t cpid;
19 struct user regs;
20 unsigned long int safed_eip;
21 unsigned long int addr,
22 addr_walker;
23 unsigned char data_saved[256];
24
25 if (argc != 2 || sscanf (argv[1], "%d", &cpid) != 1) {
26 printf ("usage: %s <pid>\n", argv[0]);
27 exit (EXIT_FAILURE);
28 }
29
30 printf ("pid = %d\n", cpid);
31
32 printf ("exploiting\n\n");
33
34 if (ptrace (PTRACE_ATTACH, cpid, NULL, NULL) < 0) {
35 perror ("ptrace");
36 exit (EXIT_FAILURE);
37 }
38
39 /* save data */
40 addr = 0xbffff010;
41 for (addr_walker = 0 ; addr_walker < 256 ; ++addr_walker) {
42 data_saved[addr_walker] = ptrace (PTRACE_PEEKDATA, cpid,
43 addr + addr_walker, NULL);
44 }
45 hexdump (data_saved, sizeof (data_saved));
46
47 /* write */
48 for (addr_walker = 0 ; addr_walker < sizeof (shellcode) ;
49 ++addr_walker)
50 {
51 ptrace (PTRACE_POKEDATA, cpid, addr + addr_walker,
52 shellcode[addr_walker] & 0xff);
53 }
54
55 /* redirect eip */
56 memset (&regs, 0, sizeof (regs));
57 if (ptrace (PTRACE_GETREGS, cpid, NULL, &regs) < 0) {
58 perror ("ptrace PTRACE_GETREGS");
59 exit (EXIT_FAILURE);
60 }
61 // write eip */
62 safed_eip = regs.regs.eip;
63 regs.regs.eip = 0xbffff010;
64 if (ptrace (PTRACE_SETREGS, cpid, NULL, &regs) < 0) {
65 perror ("ptrace PTRACE_GETREGS");
66 exit (EXIT_FAILURE);
67 }
68
69 if (ptrace (PTRACE_CONT, cpid, NULL, NULL) < 0) {
70 perror ("ptrace PTRACE_CONT");
71 exit (EXIT_FAILURE);
72 }
73
74 wait (NULL);
75 printf ("detrap\n");
76
77 /* restore */
78 for (addr_walker = 0 ; addr_walker < 256 ; ++addr_walker) {
79 ptrace (PTRACE_POKEDATA, cpid, addr + addr_walker,
80 data_saved[addr_walker] & 0xff);
81 }
82
83 /* restore regs */
84 regs.regs.eip = safed_eip;
85 if (ptrace (PTRACE_SETREGS, cpid, NULL, &regs) < 0) {
86 perror ("ptrace PTRACE_GETREGS");
87 exit (EXIT_FAILURE);
88 }
89
90 if (ptrace (PTRACE_DETACH, cpid, NULL, NULL) < 0) {
91 perror ("ptrace PTRACE_DETACH");
92 exit (EXIT_FAILURE);
93 }
94
95 exit (EXIT_SUCCESS);
96}
97
98
99
100void
101hexdump (unsigned char *data, unsigned int amount)
102{
103 unsigned int dp, p; /* data pointer */
104 const char trans[] =
105 "................................ !\"#$%&'()*+,-./0123456789"
106 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
107 "nopqrstuvwxyz{|}~...................................."
108 "....................................................."
109 "........................................";
110
111 for (dp = 1; dp <= amount; dp++) {
112 printf ("%02x ", data[dp-1]);
113 if ((dp % 8) == 0)
114 printf (" ");
115 if ((dp % 16) == 0) {
116 printf ("| ");
117 p = dp;
118 for (dp -= 16; dp < p; dp++)
119 printf ("%c", trans[data[dp]]);
120 printf ("\n");
121 }
122 }
123 if ((amount % 16) != 0) {
124 p = dp = 16 - (amount % 16);
125 for (dp = p; dp > 0; dp--) {
126 printf (" ");
127 if (((dp % 8) == 0) && (p != 8))
128 printf (" ");
129 }
130 printf (" | ");
131 for (dp = (amount - (16 - p)); dp < amount; dp++)
132 printf ("%c", trans[data[dp]]);
133 }
134 printf ("\n");
135
136 return;
137}
diff --git a/other/reducebind/reducebind b/other/reducebind/reducebind
new file mode 100755
index 0000000..8e58100
--- /dev/null
+++ b/other/reducebind/reducebind
Binary files differ
diff --git a/other/reducebind/reducebind.c b/other/reducebind/reducebind.c
new file mode 100644
index 0000000..6432670
--- /dev/null
+++ b/other/reducebind/reducebind.c
@@ -0,0 +1,311 @@
1/* reducebind.c - dynamic to static binary conversion utility
2 *
3 * by scut
4 *
5 * BETA SOFTWARE, USE ON YOUR OWN RISK
6 *
7 * x86/linux only so far. some binaries segfault deep in their code, but this
8 * does not seem to relate to the binary size. some binaries that have a 19mb
9 * size statically linked (qt designer for example ;) work, some small
10 * binaries, such as bash do not work.
11 */
12
13#include <sys/types.h>
14#include <sys/ptrace.h>
15#include <sys/wait.h>
16#include <sys/user.h>
17#include <sys/stat.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <errno.h>
21#include <unistd.h>
22#include <string.h>
23#include <elf.h>
24
25#define VERSION "0.1.0"
26
27/*** local prototypes */
28static void elf_dump_new (pid_t pid, const char *pathname_new,
29 const char *pathname_old);
30static void file_advance_roundup (FILE *fp, unsigned int padding);
31static Elf32_Addr elf_get_entrypoint (const char *pathname);
32
33
34int
35main (int argc, char *argv[], char *envp[])
36{
37 char * pathname;
38 char * f_argv[2];
39 pid_t fpid; /* child pid, gets ptraced */
40 struct user regs; /* PTRACE pulled registers */
41 Elf32_Addr entry;
42 char * output = "output";
43
44 fprintf (stderr, "reducebind version "VERSION"\n\n");
45
46 if (argc < 2) {
47 fprintf (stderr, "usage: %s <binary> [output]\n\n", argv[0]);
48
49 exit (EXIT_FAILURE);
50 }
51 pathname = argv[1];
52 if (argc >= 3)
53 output = argv[2];
54
55 entry = elf_get_entrypoint (pathname);
56
57 fpid = fork ();
58 if (fpid < 0) {
59 perror ("fork");
60 exit (EXIT_FAILURE);
61 }
62
63 /* child process.
64 */
65 if (fpid == 0) {
66 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
67 perror ("ptrace PTRACE_TRACEME");
68 exit (EXIT_FAILURE);
69 }
70 fprintf (stderr, " child: TRACEME set\n");
71
72 fprintf (stderr, " child: executing: %s\n", pathname);
73 close (1);
74 dup2 (2, 1);
75
76 /* prepare arguments and environment.
77 */
78 f_argv[0] = pathname;
79 f_argv[1] = NULL;
80
81 putenv ("LD_BIND_NOW=1");
82 execve (f_argv[0], f_argv, envp);
83
84 /* failed ? */
85 perror ("execve");
86 exit (EXIT_FAILURE);
87 }
88
89 wait (NULL);
90
91 memset (&regs, 0, sizeof (regs));
92
93 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
94 perror ("ptrace PTRACE_GETREGS");
95 exit (EXIT_FAILURE);
96 }
97 fprintf (stderr, "(%d) [0x%08lx] first stop\n", fpid, regs.regs.eip);
98 fprintf (stderr, "(%d) tracing until entry point is reached (0x%08x)\n",
99 fpid, entry);
100
101 while (regs.regs.eip != entry) {
102 if (ptrace (PTRACE_SINGLESTEP, fpid, NULL, NULL) < 0) {
103 perror ("ptrace PTRACE_SINGLESTEP");
104 exit (EXIT_FAILURE);
105 }
106 wait (NULL);
107
108 memset (&regs, 0, sizeof (regs));
109 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
110 perror ("ptrace PTRACE_GETREGS");
111 exit (EXIT_FAILURE);
112 }
113 fprintf (stderr, "\r(%d) [0x%08lx]", fpid, regs.regs.eip);
114 }
115
116 fprintf (stderr, "\n(%d) entry point reached\n", fpid);
117 fprintf (stderr, "(%d) dumping process memory to new ELF ET_EXEC file\n",
118 fpid);
119
120 elf_dump_new (fpid, output, pathname);
121
122 exit (EXIT_SUCCESS);
123}
124
125
126static void
127elf_dump_new (pid_t pid, const char *pathname_new, const char *pathname_old)
128{
129 FILE * fpn;
130 FILE * fpo;
131 FILE * mapsfp;
132 char maps_pathname[32];
133 char map_line[256];
134 Elf32_Ehdr eh;
135 Elf32_Phdr phdr[128];
136 unsigned int pn; /* program header table index */
137
138
139 fpn = fopen (pathname_new, "wb");
140 fpo = fopen (pathname_old, "rb");
141 if (fpn == NULL || fpo == NULL) {
142 perror ("fopen output ELF file creation");
143 exit (EXIT_FAILURE);
144 }
145
146 if (fread (&eh, sizeof (eh), 1, fpo) != 1) {
147 perror ("fread ELF header");
148 exit (EXIT_FAILURE);
149 }
150 fclose (fpo);
151
152 /* kill header values */
153 eh.e_shoff = 0x0; /* we do not need any sections for loading */
154 eh.e_shnum = 0;
155 eh.e_shstrndx = 0;
156
157 /* the program header table will be fixed later */
158 eh.e_phoff = 0;
159 eh.e_phnum = 0;
160
161 fwrite (&eh, sizeof (eh), 1, fpn);
162
163 snprintf (maps_pathname, sizeof (maps_pathname) - 1,
164 "/proc/%d/maps", pid);
165 maps_pathname[sizeof (maps_pathname) - 1] = '\0';
166 mapsfp = fopen (maps_pathname, "r");
167 if (mapsfp == NULL) {
168 perror ("fopen map file");
169 exit (EXIT_FAILURE);
170 }
171
172 while (1) {
173 Elf32_Phdr * ph;
174 unsigned int addr_start,
175 addr_end,
176 addr_walker;
177 char map_perm[8];
178 unsigned char data_saved[sizeof (unsigned long int)];
179
180
181 memset (map_line, '\0', sizeof (map_line));
182 if (fgets (map_line, sizeof (map_line) - 1, mapsfp) == NULL)
183 break;
184 map_line[sizeof (map_line) - 1] = '\0';
185
186 fprintf (stderr, "%s", map_line);
187 if (sscanf (map_line, "%08x-%08x %7[rwxp-] ",
188 &addr_start, &addr_end, map_perm) != 3)
189 {
190 perror ("invalid map-line");
191
192 exit (EXIT_FAILURE);
193 }
194
195 /* we do not need the stack in here.
196 */
197 if (addr_end == 0xc0000000)
198 continue;
199
200 file_advance_roundup (fpn, PAGE_SIZE);
201
202 ph = &phdr[eh.e_phnum];
203 eh.e_phnum += 1;
204 memset (ph, 0x00, sizeof (Elf32_Phdr));
205
206 ph->p_type = PT_LOAD;
207 ph->p_offset = ftell (fpn);
208 ph->p_vaddr = addr_start;
209 ph->p_paddr = 0x0;
210 ph->p_filesz = ph->p_memsz = addr_end - addr_start;
211 ph->p_flags = 0;
212 if (map_perm[0] == 'r')
213 ph->p_flags |= PF_R;
214 if (map_perm[1] == 'w')
215 ph->p_flags |= PF_W;
216 if (map_perm[2] == 'x')
217 ph->p_flags |= PF_X;
218 ph->p_align = PAGE_SIZE;
219
220 /* save segment data, assuming addr is page aligned
221 */
222 for (addr_walker = 0 ; addr_walker < (addr_end - addr_start);
223 addr_walker += sizeof (data_saved))
224 {
225 errno = 0;
226
227 *((unsigned long int *) &data_saved[0]) =
228 ptrace (PTRACE_PEEKDATA, pid,
229 addr_start + addr_walker, NULL);
230
231 if (errno == 0 && fwrite (&data_saved[0],
232 sizeof (data_saved), 1, fpn) != 1)
233 {
234 perror ("fwrite segment");
235
236 exit (EXIT_FAILURE);
237 } else if (errno != 0) {
238 fprintf (stderr,
239 "[0x%08x] invalid PTRACE_PEEKDATA\n",
240 addr_start + addr_walker);
241
242 exit (EXIT_FAILURE);
243 }
244 }
245 }
246
247 fclose (mapsfp);
248
249 /* now write program header table
250 */
251 file_advance_roundup (fpn, PAGE_SIZE);
252 eh.e_phoff = ftell (fpn);
253
254 for (pn = 0 ; pn < eh.e_phnum ; ++pn) {
255 if (fwrite (&phdr[pn], sizeof (Elf32_Phdr), 1, fpn) != 1) {
256 perror ("fwrite program header");
257 exit (EXIT_FAILURE);
258 }
259 }
260
261 fseek (fpn, 0, SEEK_SET);
262 if (fwrite (&eh, sizeof (Elf32_Ehdr), 1, fpn) != 1) {
263 perror ("fwrite final ELF header");
264 exit (EXIT_FAILURE);
265 }
266
267 fclose (fpn);
268 chmod (pathname_new, 0700);
269}
270
271
272static void
273file_advance_roundup (FILE *fp, unsigned int padding)
274{
275 unsigned int pos;
276
277 pos = ftell (fp);
278 if (pos % padding == 0)
279 return;
280
281 pos %= padding;
282 pos = padding - pos;
283
284 fseek (fp, pos, SEEK_CUR);
285}
286
287
288static Elf32_Addr
289elf_get_entrypoint (const char *pathname)
290{
291 FILE * fp;
292 Elf32_Ehdr eh;
293
294
295 fp = fopen (pathname, "rb");
296 if (fp == NULL) {
297 perror ("fopen input ELF file");
298 exit (EXIT_FAILURE);
299 }
300
301 if (fread (&eh, sizeof (eh), 1, fp) != 1) {
302 perror ("fread");
303 exit (EXIT_FAILURE);
304 }
305
306 fclose (fp);
307
308 return (eh.e_entry);
309}
310
311