Skip to content

Commit

Permalink
Merge pull request #16 from lapla-cogito/encfunction
Browse files Browse the repository at this point in the history
function name encryption
  • Loading branch information
lapla-cogito authored Aug 22, 2024
2 parents 0b83161 + f2255d2 commit 3e2bb81
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 14 deletions.
129 changes: 129 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
aes-stream = "0.2.1"
anyhow = "1.0.86"
clap = { version = "4.5.3", features = ["derive"] }
memmap2 = "0.9.4"
rust-crypto = "0.2.36"
thiserror = "1.0.63"
77 changes: 63 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ A CLI application to obfuscate ELF file(s)
Usage: cattleya [OPTIONS]
Options:
-i, --input <INPUT> input file name [default: ]
-o, --output <OUTPUT> output file name [default: ]
-c, --class change architecture class in the ELF
-e, --endian change endian in the ELF
-s, --sechdr nullify section header in the ELF
--symbol nullify symbols in the ELF
--comment nullify comment section in the ELF
--section <SECTION> nullify section in the ELF [default: ]
-r, --recursive <RECURSIVE> recursive [default: ]
-g, --got perform GOT overwrite
--got-l <GOT_L> GOT overwrite target library function name [default: ]
--got-f <GOT_F> GOT overwrite target function name [default: ]
-h, --help Print help
-V, --version Print version
-i, --input <INPUT> input file name [default: ]
-o, --output <OUTPUT> output file name [default: ]
-c, --class change architecture class in the ELF
-e, --endian change endian in the ELF
-s, --sechdr nullify section header in the ELF
--symbol nullify symbols in the ELF
--comment nullify comment section in the ELF
--section <SECTION> nullify section in the ELF [default: ]
-r, --recursive <RECURSIVE> recursive [default: ]
-g, --got perform GOT overwrite
--got-l <GOT_L> GOT overwrite target library function name [default: ]
--got-f <GOT_F> GOT overwrite target function name [default: ]
--encrypt encrypt function name with the given key
--encrypt-f <ENCRYPT_F> encryption target function name [default: ]
--encrypt-key <ENCRYPT_KEY> encryption key [default: ]
-h, --help Print help
-V, --version Print version
```

Both input and recursive options cannot be empty.
Expand Down Expand Up @@ -143,12 +146,58 @@ Hex dump of section '.comment':
0x00000020 00000000 00000000 000000 ...........
```

## function name encryption

Encrypts the name of a specific function with AES 256bit using the given key:

```
$ cargo run -- -i bin/test_64bit --encrypt --encrypt-f fac --encrypt-key foo -o bin/res_enc
start obfuscating bin/test_64bit...
obfuscation done!
$ ./bin/res_enc
fac(1)=1
fib(1)=1
fac(5)=120
fib(5)=5
fac(10)=3628800
fib(10)=55
$ objdump -d bin/res_enc
...
000000000000120c <main>:
120c: f3 0f 1e fa endbr64
1210: 55 push %rbp
1211: 48 89 e5 mov %rsp,%rbp
1214: 48 83 ec 10 sub $0x10,%rsp
1218: 89 7d fc mov %edi,-0x4(%rbp)
121b: 48 89 75 f0 mov %rsi,-0x10(%rbp)
121f: bf 01 00 00 00 mov $0x1,%edi
1224: e8 20 ff ff ff call 1149 <�0,>
1229: bf 01 00 00 00 mov $0x1,%edi
122e: e8 6a ff ff ff call 119d <fib>
1233: bf 05 00 00 00 mov $0x5,%edi
1238: e8 0c ff ff ff call 1149 <�0,>
123d: bf 05 00 00 00 mov $0x5,%edi
1242: e8 56 ff ff ff call 119d <fib>
1247: bf 0a 00 00 00 mov $0xa,%edi
124c: e8 f8 fe ff ff call 1149 <�0,>
1251: bf 0a 00 00 00 mov $0xa,%edi
1256: e8 42 ff ff ff call 119d <fib>
125b: b8 00 00 00 00 mov $0x0,%eax
1260: c9 leave
1261: c3 ret
...
```

Function name "fac" is encrypted.

## GOT overwrite

Overwrites the GOT section with a specified value

```
$ cattleya -i bin/got --got --got-l system --got-f secret -o bin/res_got
start obfuscating bin/got...
obfuscation done!
$ ./bin/res_got
secret function called
```
Expand Down
19 changes: 19 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ struct Args {
got_l: String,
#[arg(long, help = "GOT overwrite target function name", default_value = "")]
got_f: String,
#[arg(
long,
help = "encrypt function name with the given key",
default_value = "false"
)]
encrypt: bool,
#[arg(long, help = "encryption target function name", default_value = "")]
encrypt_f: String,
#[arg(long, help = "encryption key", default_value = "")]
encrypt_key: String,
}

fn main() -> crate::error::Result<()> {
Expand Down Expand Up @@ -140,6 +150,15 @@ fn exec_obfus(input_path: &str, output_path: &str, args: &Args) -> crate::error:

obfuscator.got_overwrite(&args.got_l, &args.got_f)?;
}
if args.encrypt {
if args.encrypt_f.is_empty() || args.encrypt_key.is_empty() {
return Err(crate::error::Error::InvalidOption(
"target function name and encryption key is required",
));
}

obfuscator.encrypt_function_name(&args.encrypt_f, &args.encrypt_key)?;
}

println!("obfuscation done!");
Ok(())
Expand Down
46 changes: 46 additions & 0 deletions src/obfus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,50 @@ impl Obfuscator {

Err(crate::error::Error::Obfuscation("failed to overwrite GOT"))
}

pub fn encrypt_function_name(&mut self, function: &str, key: &str) -> crate::error::Result<()> {
let mut key_bytes = [0; 32];
if key.len() > 32 {
return Err(crate::error::Error::InvalidOption(
"key length must be less than 32",
));
}
for (i, byte) in key.bytes().enumerate() {
key_bytes[i] = byte;
}
let encryptor = crypto::aessafe::AesSafe256Encryptor::new(&key_bytes);

let tmp_file = std::fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open("/tmp/cattleya_encrypted_function_name")
.map_err(crate::error::Error::CreateFile)?;
let mut writer = aesstream::AesWriter::new(tmp_file, encryptor).unwrap();
writer
.write_all(function.as_bytes())
.map_err(crate::error::Error::Io)?;

let mut encrypted_function_name = Vec::new();
let mut tmp_file = std::fs::File::open("/tmp/encrypted_function_name")
.map_err(crate::error::Error::OpenFile)?;
tmp_file
.read_to_end(&mut encrypted_function_name)
.map_err(crate::error::Error::Io)?;

let idx = self.string_table.find(function).unwrap();
let (section_addr, _, _, _) = self.get_section(".strtab").unwrap();
if function.len() >= 16 {
self.output[section_addr + idx..section_addr + idx + function.len()]
.copy_from_slice(&encrypted_function_name);
} else {
let mut encrypted_function_name = encrypted_function_name;
encrypted_function_name.resize(function.len(), 0);
self.output[section_addr + idx..section_addr + idx + function.len()]
.copy_from_slice(&encrypted_function_name);
}

Ok(())
}
}

0 comments on commit 3e2bb81

Please sign in to comment.