A Rust program obfusgator.
To self obfusgator:
rustc obfusgator.rs && ./obfusgator
To obfusgator another program:
rustc obfusgator && ./obfusgator lib.rs
// rustc obfusgator.rs
use std :: env ; use
std :: fs ; use std
:: io ; const
GATOR_RIGHT : & [ &
str ] = & [
concat!
( " "
,
" "
,
" "
,
" "
,
" " ,
" " , " "
, " " , " "
) , concat! ( " " , " " ,
" 00000000" , "000000000" , "0 " ,
" " , " " , " " , " " )
, concat! ( " " , " 0000000" , "000000000" ,
"0000 " , " " , " " , " " ,
" " , " " ) , concat! ( " 0" , "000000000"
, "000000000" , "000 " , " " , " "
, " " , " " , " " ) ,
concat! ( " 0" , "000000000" ,
"000000000" , "0 " , " " ,
" " , " " , " " , " "
) , concat! ( " 0000" , "000000000" , "000 "
, " " , " " , " " , " "
, " " , " " ) , concat! ( " 0000" , "0000 " , " "
, " " , " " , " " , " " , " " ,
" " ) , concat! ( " 000000" , "000000 " , " " , " "
, " " , " " , " " , " " , " " ) , concat!
( " 000000"
, "0000 " , " "
, " " ,
" " , " " ,
" " , " " ,
" " ) , concat! (
" 000000" , "00 " ,
" " , " "
, " " ,
" " ,
" "
,
" "
,
" "
) , concat! (
" 000000" ,
"00 " ,
" " ,
" " ,
" "
, " "
,
" "
,
" "
,
" "
) ,
concat! (
" 000000" , "0 "
, " " , " "
, " " , " " ,
" " , " " , " " ) ,
concat! ( " 00000000" , "0 " , " " , " "
, " " , " " , " " , " " ,
" " ) , concat! ( " 00000000" , " " ,
" " , " " , " " , " " , " "
, " " , " " ) , concat! ( " 0000000 "
, " " , " " , " " ,
" " , " " , " " ,
" " , " " ) , concat! (
" 00000000" , " " , " " , " " ,
" " , " " , " " , " " ,
" 00000 " ) , concat! ( " 00000000" , " " , " "
, " " , " 00000" , "000 " , " " , " 0000000" , "00000 "
) , concat! ( " 00000000" , " " , " " , " " , " 00000"
, "000 " , " " , " 0000000" , "000000 " ) , concat! (
" 00000000" , "0000000 " , " " , " " , " 000000 " , " 00000"
, "000000 "
, " 0000" , "000000 "
) , concat! ( " 00000000"
, "000000000" , "000 "
, " 000" , "00000 "
, " 00000" ,
"000000000" , "0 " ,
" " ) , concat! (
" 00000000" , "000000000"
, "000000000"
,
"000000000"
,
"00000 "
,
" 00000" ,
"00000000 " ,
" 00 " , " "
) , concat! (
" 00000000" ,
"000000000"
, "000000000"
,
"000000000"
,
"000000000"
,
"000000000"
,
"0000000 " ,
" " , " "
) , concat! ( " 00000000"
, "000000000" , "000000000" , "000000000" ,
"000000000" , "000000000" , "000 " ,
" " , " " ) , concat! ( " 00000000" , "000000000"
, "000000000" , "000000000" , "000000000" , "000000000" ,
"0 0 " , " " , " " ) , concat! (
" 00000000" , "000000000" , "000000000" , "000000000" ,
"000000000" , "000000 " , " 0 " , " "
, " " ) , concat! ( " 00000000" ,
"000000000" , "000000000" , "000000000" ,
"000000000" , "00 " , " " ,
" " , " " ) , concat! ( " 00000000"
, "000000000" , "000000000" , "000000000" , "000000000"
, " " , " " , " " , " "
) , concat! ( " 00000000" , "000000000" , "000000000" , "000000000" ,
"000000000" , "0 " , " " , " " , " " ) , concat!
( " 00000000" , "000000000" , "000000000" , "000000000" , "000000000" ,
"00 0" , " " , " " , " " ) , concat! ( " 000000"
, "000000000"
, "000000000" , "000000000"
, "000000000" ,
"00000000 " , " 0 " ,
" " , " " )
, concat! ( " 000000"
, "000000000" , "000000000"
, "000000000" , "000000000"
, "000000000" ,
"0 0 " ,
" "
,
" "
) ,
concat!
( " 000000" ,
"000000000" ,
"000000000" ,
"000000000" ,
"000000000" ,
"000000000"
, "000000000"
,
"000000000"
,
"000000000"
) , concat!
(
" 000000"
, "000000000"
, "000000000" , "000000000"
, "000000000" , "000000000"
, "000000000" , "000000000" ,
"000000000" ) , concat! ( " 000000" ,
"000000000" , "000000000" , "000000000" , "000000000" , "000000000"
, "000000000" , "000000000" , "0000000 " ) , concat! (
" 000000" , "000000000" , "000000000" , "000000000" ,
"000000000" , "000000000" , "000000000" , "000000000" , "000000000"
) , concat! ( " 0000" , "000 " , " "
, " 000000" , "0 " , " " ,
" " , " " , " " ) ,
concat! ( " 0000" , "0000000 " ,
" " , " 000000" , "00 000000" , "000 " ,
" " , " " , " " ) , concat! (
" 0" , "0000000 " , " " , " 000" ,
"000000000" , "00 " , " " , " " , " " ) , concat!
( " 0" , "000000000" , " " , " 000000" , "000000000" ,
"00 " , " " , " " , " " ) , concat! (
" 0" , "000000000" , "0 " , " 0000" , "000000000" , "00 "
, " "
, " " , " "
) , concat! ( " "
, " " , " "
, " " , " "
, " " ,
" " , " " ,
" " ) , concat! (
" " , " "
, " "
,
" "
,
" 00000000"
,
"000000000" ,
"0000000 " ,
" " ,
" " ) ,
concat! (
" "
, " "
,
" "
,
" "
,
" 00000"
,
"000000000" ,
"000000000" , "00000 "
, " " ) , concat! (
" " , " " , " " ,
" " , " 000" , "000000000" ,
"000000000" , "0000 " , " " ) , concat! ( " "
, " " , " " , " " , " 00" ,
"000000000" , "000000000" , "000 " , " " )
, concat! ( " " , " " , " " , " "
, " " , " 0" , "000000000" , "000 "
, " " ) , concat! ( " " ,
" " , " " , " " ,
" " , " " , " 00" ,
"0000 " , " " ) , concat! ( " "
, " " , " " , " " , " "
, " " , " 00" , "000000 " , " " )
, concat! ( " " , " " , " " , " " , " "
, " " , " " , "0000000 " , " " ) , concat! ( " "
, " " , " " , " " , " " , " " ,
" " , " 0000000 " , " " ) , concat! ( " " , " "
, " "
, " " , " "
, " " ,
" " , " 00000" ,
" " ) , ] ; const
GATOR_LEFT : & [ & str ]
= & [ concat! ( " "
, " " , " "
, " " ,
" " ,
" "
,
" "
,
" "
, " " ) ,
concat! ( " "
, " " ,
" " ,
" " ,
" 00"
, "000000000"
,
"0000000 "
,
" "
,
" "
) ,
concat! (
" " , " "
, " " , " "
, " " , " 00000" ,
"000000000" , "000000 " , " " ) ,
concat! ( " " , " " , " " , " "
, " " , " 0000" , "000000000" , "000000000" ,
" " ) , concat! ( " " , " " ,
" " , " " , " " , " 00" , "000000000"
, "000000000" , " " ) , concat! ( " "
, " " , " " , " " ,
" " , " " , " 0000" ,
"000000000" , "000 " ) , concat! (
" " , " " , " " , " " ,
" " , " " , " " , " 00000" ,
"000 " ) , concat! ( " " , " " , " "
, " " , " " , " " , " " , " 0000000" , "00000 "
) , concat! ( " " , " " , " " , " " , " "
, " " , " " , " 00000" , "00000 " ) , concat! (
" " , " " , " " , " " , " " , " "
, " "
, " 000" , "00000 "
) , concat! ( " "
, " " , " "
, " " , " "
, " " ,
" " , " 000" ,
"00000 " ) , concat! (
" " , " "
, " "
,
" "
,
" "
,
" " ,
" " ,
" 00" , "00000 "
) , concat! (
" " ,
" "
, " "
,
" "
,
" "
,
" "
,
" " ,
" 00" , "0000000 " )
, concat! ( " " ,
" " , " " , " " ,
" " , " " , " " ,
" 0" , "0000000 " ) , concat! ( " " , " "
, " " , " " , " " , " " ,
" " , " " , "0000000 " ) , concat! (
" 00000 " , " " , " " , " " ,
" " , " " , " " , " 0"
, "0000000 " ) , concat! ( " 000000" ,
"000000 " , " " , " 0000" ,
"0000 " , " " , " " ,
" 0" , "0000000 " ) , concat! ( " 0000000"
, "000000 " , " " , " 0000" , "0000 "
, " " , " " , " 0" , "0000000 " )
, concat! ( " 0000000" , "000 " , " 0000000" , "0000 " , " 000000 "
, " " , " " , " 00000000" , "0000000 " ) , concat! ( " "
, " 00" , "000000000" , "0000 " , " 000000" , "00 " ,
" 0000" , "000000000" , "0000000 " ) , concat! ( " " , " 00 "
, "000000000"
, "0000 " , " 000000"
, "000000000" ,
"000000000" , "000000000" ,
"0000000 " ) , concat! (
" " , " "
, " 0000000" , "000000000"
, "000000000" , "000000000"
, "000000000" ,
"000000000" ,
"00000000 "
) ,
concat!
(
" "
, " " ,
" 000" ,
"000000000" ,
"000000000" ,
"000000000" ,
"000000000"
, "000000000"
,
"0000000 "
) ,
concat!
(
" "
,
" " ,
" 0 0" , "000000000"
, "000000000" , "000000000"
, "000000000" , "000000000" ,
"00000000 " ) , concat! ( " " ,
" " , " 0 " , " 000000" , "000000000" , "000000000"
, "000000000" , "000000000" , "00000000 " ) , concat! (
" " , " " , " " , " 00" ,
"000000000" , "000000000" , "000000000" , "000000000" , "00000000 "
) , concat! ( " " , " " , " "
, " " , "000000000" , "000000000" ,
"000000000" , "000000000" , "00000000 " ) ,
concat! ( " " , " " ,
" " , " 0" , "000000000" , "000000000" ,
"000000000" , "000000000" , "00000000 " ) , concat! (
" " , " " , " " , "0 00" ,
"000000000" , "000000000" , "000000000" , "000000000" , "00000000 " ) , concat!
( " " , " " , " 0 " , " 00000000" , "000000000" ,
"000000000" , "000000000" , "000000000" , "00000 " ) , concat! (
" " , " " , " 0 0" , "000000000" , "000000000" , "000000000"
, "000000000"
, "000000000" , "000000 "
) , concat! ( "000000000"
, "000000000" , "000000000"
, "000000000" , "000000000"
, "000000000" ,
"000000000" , "000000000" ,
"00000000 " , " " ) ,
concat! ( "000000000" ,
"000000000" ,
"000000000"
,
"000000000"
,
"000000000"
, "000000000" ,
"000000000" ,
"000000000" ,
"00000000 " , " " )
, concat! (
" 0000000"
, "000000000"
,
"000000000"
,
"000000000"
,
"000000000"
,
"000000000" ,
"000000000" , "000000000"
, "000000 " ) , concat! (
"000000000" , "000000000" , "000000000" ,
"000000000" , "000000000" , "000000000" ,
"000000000" , "000000000" , "00000000 " , " " ) , concat!
( " " , " " , " " , " " ,
" " , " " , " 0000" , "000 0" ,
"000000 " ) , concat! ( " " , " " , " "
, " 000" , "000000 00" , "000000 " , " "
, " 0000000" , "0000 " ) , concat! (
" " , " " , " " ,
" 00" , "000000000" , "000 " ,
" " , " 0000000" , "0 " ) , concat!
( " " , " " , " " , " 00"
, "000000000" , "000000 " , " " , "000000000"
, "0 " ) , concat! ( " " , " " , " " ,
" 00" , "000000000" , "0000 " , " 0" , "000000000" ,
"0 " ) , concat! ( " " , " " , " " ,
" " , " " , " " , " " , " " , " "
) , concat!
( " " , " "
, " 0000000" ,
"000000000" , "00000000 " ,
" " , " " ,
" " , " "
) , concat! ( " " ,
" 00000" , "000000000"
, "000000000" ,
"00000 " ,
" "
,
" "
,
" "
, " " ) ,
concat! ( " "
, " 0000" ,
"000000000" ,
"000000000" ,
"000 "
, " "
,
" "
,
" "
,
" "
) ,
concat! (
" " , " 000"
, "000000000" , "000000000"
, "00 " , " " ,
" " , " " , " " ) ,
concat! ( " " , " 000" , "000000000" , "0 "
, " " , " " , " " , " " ,
" " ) , concat! ( " " , " 00000" ,
"0 " , " " , " " , " " , " "
, " " , " " ) , concat! ( " "
, " 0000000" , "0 " , " " ,
" " , " " , " " ,
" " , " " ) , concat! (
" " , " 0000000 " , " " , " " ,
" " , " " , " " , " " ,
" " ) , concat! ( " " , "0000000 " , " "
, " " , " " , " " , " " , " " ,
" " ) , concat! ( " 0" , "0000 " , " " , " "
, " " , " " , " " , " " , " " ) , ]
; const MAX_TOKEN_LEN : usize = 12 ; fn main ( ) -> io :: Result < ( ) > { let
args : Vec <
String > = env :: args ( ) .
collect ( ) ; let
file_path = if args . len ( )
> 1 { & args [ 1 ] } else
{ file ! ( ) } ; let src
= fs :: read_to_string (
file_path ) .
unwrap_or_else ( | _ |
"" . into ( )
) ; if
src .
is_empty
( ) {
return
Ok ( ( ) ) ; } let
mut tokens = tokenize
( & src ) ; tokens =
split_long_tokens (
tokens ) ; tokens
. reverse
( ) ; println
! ( concat!
(
"// rustc "
,
"obfusgato"
, "r.rs"
) ) ; let
mut row = 0 ;
let mut facing_right = true ; while
! tokens . is_empty ( ) { let gator
= if facing_right { GATOR_RIGHT } else {
GATOR_LEFT } ; let gator_row = row % gator .
len ( ) ; if gator_row == 0 && row > 0 { facing_right =
! facing_right ; } let line_mask = gator [ gator_row ] ; let
mut line_buffer = String :: new ( ) ; let chars : Vec <
char > = line_mask . chars ( ) . collect ( ) ; let mut i
= 0 ; while i < chars . len ( ) { if chars [ i ] == '0'
{ let mut block_len = 0 ; while i + block_len
< chars . len ( ) && chars [ i + block_len ]
== '0' { block_len += 1 ; } let mut current_len
= 0 ; while current_len < block_len { if let Some
( tok ) = tokens . pop ( ) { let s = format ! ( "{} "
, tok ) ; if current_len + s . len ( ) > block_len + 3
&& current_len > 0 { tokens . push ( tok ) ; break ; } line_buffer . push_str
( & s ) ; current_len += s . len ( ) ; } else { break ; } } while current_len
< block_len { line_buffer . push ( ' ' ) ; current_len += 1 ; } i += block_len
; } else { line_buffer . push ( ' ' ) ; i += 1 ; } } println ! ( "{}" ,
line_buffer .
trim_end ( ) ) ; row += 1 ; }
Ok ( ( ) ) } fn
split_long_tokens ( tokens : Vec <
String > ) -> Vec < String
> { let mut result = Vec
:: new ( ) ; for tok in tokens
{ if tok . starts_with (
'"' ) && tok . ends_with
( '"' ) && tok
. len
( ) >
MAX_TOKEN_LEN
{ let
inner
= & tok [ 1 .. tok
. len ( ) - 1 ] ; let
chunk_size =
MAX_TOKEN_LEN - 3 ;
let chunks : Vec
< String
> = inner .
as_bytes (
) . chunks
(
chunk_size
) . map (
| c | std
:: str
:: from_utf8
( c ) . unwrap_or ( "" ) .
to_string ( ) ) . collect
( ) ; if chunks . len ( ) > 1 { result . push
( "concat!" . into ( ) ) ; result . push (
"(" . into ( ) ) ; for ( i , chunk ) in chunks . iter ( )
. enumerate ( ) { if i > 0 { result . push ( "," . into ( )
) ; } result . push ( format ! ( "\"{}\"" , chunk ) ) ;
} result . push ( ")" . into ( ) ) ; } else { result .
push ( tok ) ; } } else { result . push ( tok ) ; } }
result } const MULTI_CHAR_OPS : & [ & str ] =
& [ "..=" , "..." , "=>" , "->" , "::" , "&&"
, "||" , "==" , "!=" , "<=" , ">=" , "+=" ,
"-=" , "*=" , "/=" , "%=" , "&=" , "|=" , "^=" ,
"<<=" , ">>=" , ".." , "<<" , ">>" , ] ; fn tokenize (
input : & str ) -> Vec < String > { let mut tokens = Vec ::
new ( ) ; let chars : Vec < char > = input . chars ( ) . collect ( ) ; let mut pos
= 0 ; while pos < chars . len ( ) { let c = chars [ pos ] ; if c . is_whitespace
( ) { pos += 1 ; } else if c == '/' && pos + 1 < chars . len ( ) && chars [
pos + 1 ] == '/' { pos += 2 ; while pos < chars . len ( ) && chars [ pos ] != '\n'
{ pos += 1 ; } }
else if c == '/' && pos + 1 <
chars . len ( ) && chars
[ pos + 1 ] == '*' { pos += 2
; while pos + 1 < chars . len
( ) && ! ( chars [ pos ]
== '*' && chars [ pos + 1 ]
== '/' ) { pos += 1 ; } pos
+= 2 ; } else if c == '"'
{ let mut s =
String
:: new (
) ; s .
push (
chars
[ pos ] ) ; pos +=
1 ; let mut escaped
= false ; while pos <
chars . len ( ) { let
n = chars [ pos
] ; s .
push ( n ) ;
pos += 1 ;
if escaped
{ escaped
= false
; } else
if n ==
'\\' {
escaped = true
; } else if n == '"' { break
; } } tokens . push ( s ) ;
} else if c == '\'' { let mut s = String ::
new ( ) ; s . push ( chars [ pos ] ) ; pos +=
1 ; if pos < chars . len ( ) && ( chars [ pos ] . is_alphabetic
( ) || chars [ pos ] == '_' ) { while pos < chars . len ( )
&& ( chars [ pos ] . is_alphanumeric ( ) || chars [ pos
] == '_' ) { s . push ( chars [ pos ] ) ; pos += 1 ; } if
pos < chars . len ( ) && chars [ pos ] == '\'' { s .
push ( chars [ pos ] ) ; pos += 1 ; } } else {
let mut escaped = false ; while pos < chars
. len ( ) { let n = chars [ pos ] ; s . push
( n ) ; pos += 1 ; if escaped { escaped = false ;
} else if n == '\\' { escaped = true ; } else if n ==
'\'' { break ; } } } tokens . push ( s ) ; } else if c
. is_alphanumeric ( ) || c == '_' { let mut w = String :: new ( ) ; while pos
< chars . len ( ) && ( chars [ pos ] . is_alphanumeric ( ) || chars [ pos ] ==
'_' ) { w . push ( chars [ pos ] ) ; pos += 1 ; } tokens . push ( w ) ; } else
{ let remaining : String = chars [ pos .. ] . iter ( ) . collect ( ) ; let mut
matched = false
; for op in MULTI_CHAR_OPS { if
remaining . starts_with
( op ) { tokens . push ( op
. to_string ( ) ) ; pos +=
op . len ( ) ; matched =
true ; break ; } } if !
matched { tokens . push (
c . to_string ( ) ) ; pos
+= 1 ; } } }
tokens
}- https://github.com/ringtailsoftware/obfusgator for the idea