F
FLASHCODER
Guest
I'm trying decrypt a shellcode that is a Delphi 10 executable, using XTEA algorithm. The following code is a example of EXE crypter with a stub(shellcode decrypter) and the trouble is when i'm replacing encrypted shellcode by decrypted shellcode on byte array, in others words is failing in this line of stub app:
for (int j = 0; j < BLOCK_SIZE; j++)
memcpy(&shellcode_decrypted[(i * BLOCK_SIZE) + j], &data[j], sizeof(unsigned char)); // < failing here
The code below was tested and is working with encrypted shellcode of C++ console app (Visual Studio) and also with Delphi 7 console app. I want turn it compatible to decrypt shellcode of any executable file (or at least any Delphi version).
Some suggestion?
This is complete code:
Crypter:
#include <iostream>
#include <fstream>
#include <stdint.h>
#include <cstring>
#include <cstdlib>
#include <stdlib.h>
using namespace std;
unsigned int key[4] = { 0xBB8,0xFA0,0x1388,0x1B58 };
#define BLOCK_SIZE 8
/*
XTea reference code taken from
XTEA - Wikipedia
*/
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0; v[1] = v1;
}
void crypto(char filepath[]) {
fstream dat(filepath, ios::in | ios:ut | ios::binary); //Open the file
if (!dat) {
cout << "I can not read from the file you provided. Sorry :\(" << endl;
system("pause");
exit(-1);
}
unsigned size;
dat.seekg(0, ios::end);
size = dat.tellg();
dat.seekg(0, ios::beg);
dat.clear();
unsigned pos;
int n_blocks = size / BLOCK_SIZE;
if (size % BLOCK_SIZE != 0)
++n_blocks;
unsigned char data[BLOCK_SIZE];
for (int i = 0; i < n_blocks; i++) { //for every character in the executable, encipher the character
pos = dat.tellg();
dat.read((char*)data, BLOCK_SIZE);
encipher(32, (uint32_t*)data, key);
dat.seekp(pos);
dat.write((char*)data, BLOCK_SIZE);
dat.flush();
memset(data, 0, BLOCK_SIZE);
}
dat.close(); //all the enciphered data was sent back the the executable
}
int shellcode(string file) {
FILE* sf; //executable file
FILE* f; //shellcode.h
int i, c;
const char* arr_name;
sf = fopen(file.c_str(), "rb");
if (sf == NULL) {
fprintf(stderr, "fopen(%s) Failed. Could'nt open file.", file.c_str());
return 1;
}
arr_name = "shellcode";
f = fopen("shellcode.h", "w");
fprintf(f, "unsigned char %s[] = {", arr_name);
for (i = 0;; i++) { //grab the shellcode and drop it in
if ((c = fgetc(sf)) == EOF) break; //shellcode.h
if (i != 0) fprintf(f, ",");
if ((i % 12) == 0) fprintf(f, "\n\t");
fprintf(f, "0x%.2X", (unsigned char)c);
}
fprintf(f, "\n\t};\n");
fprintf(f, "const unsigned int size = %i;\n", i);
fclose(sf);
fclose(f);
return 0;
}
int main(int argc, char* argv[]) {
if (argc < 2) { //RTFM
fprintf(stderr, "Usage: %s [filepath]\n", argv[0]);
return 1;
}
crypto(argv[1]); //cipher
cout << "Finished Ciphering " << endl;
shellcode(argv[1]); //generate shellcode
cout << "Finished Generating " << argv[1] << endl;
system("pause"); //press any key to continue
return 0;
}
Stub:
#include <Windows.h>
#include "shellcode.h" /*load up your programs shellcode*/
#include <stdint.h>
#include <stdio.h>
unsigned int key[4] = { 0xBB8,0xFA0,0x1388,0x1B58 }; /* Chose a password in hex */
#define BLOCK_SIZE 8 /* Make sure you change both */
/* xtea.cpp and stub.cpp */
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
int main() {
unsigned char shellcode_decrypted[size]; //Make a slot for your shellcode
int n_blocks = size / BLOCK_SIZE;
if (size % BLOCK_SIZE != 0) //pad the shellcode
++n_blocks;
unsigned char data[BLOCK_SIZE];
for (int i = 0; i < n_blocks; i++) {
memcpy(&data, &shellcode[i * BLOCK_SIZE], BLOCK_SIZE); //copy the shellcode into the data buffer
decipher(32, (uint32_t*)data, key); //de-xtea it
for (int j = 0; j < BLOCK_SIZE; j++)
memcpy(&shellcode_decrypted[(i * BLOCK_SIZE) + j], &data[j], sizeof(unsigned char));
memset(data, 0, BLOCK_SIZE);
}
FILE* file = fopen("C:\\Original.exe", "wb");
fwrite(shellcode_decrypted, 1, size, file);
fclose(file);
return 0;
}
Continue reading...
for (int j = 0; j < BLOCK_SIZE; j++)
memcpy(&shellcode_decrypted[(i * BLOCK_SIZE) + j], &data[j], sizeof(unsigned char)); // < failing here
The code below was tested and is working with encrypted shellcode of C++ console app (Visual Studio) and also with Delphi 7 console app. I want turn it compatible to decrypt shellcode of any executable file (or at least any Delphi version).
Some suggestion?
This is complete code:
Crypter:
#include <iostream>
#include <fstream>
#include <stdint.h>
#include <cstring>
#include <cstdlib>
#include <stdlib.h>
using namespace std;
unsigned int key[4] = { 0xBB8,0xFA0,0x1388,0x1B58 };
#define BLOCK_SIZE 8
/*
XTea reference code taken from
XTEA - Wikipedia
*/
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0; v[1] = v1;
}
void crypto(char filepath[]) {
fstream dat(filepath, ios::in | ios:ut | ios::binary); //Open the file
if (!dat) {
cout << "I can not read from the file you provided. Sorry :\(" << endl;
system("pause");
exit(-1);
}
unsigned size;
dat.seekg(0, ios::end);
size = dat.tellg();
dat.seekg(0, ios::beg);
dat.clear();
unsigned pos;
int n_blocks = size / BLOCK_SIZE;
if (size % BLOCK_SIZE != 0)
++n_blocks;
unsigned char data[BLOCK_SIZE];
for (int i = 0; i < n_blocks; i++) { //for every character in the executable, encipher the character
pos = dat.tellg();
dat.read((char*)data, BLOCK_SIZE);
encipher(32, (uint32_t*)data, key);
dat.seekp(pos);
dat.write((char*)data, BLOCK_SIZE);
dat.flush();
memset(data, 0, BLOCK_SIZE);
}
dat.close(); //all the enciphered data was sent back the the executable
}
int shellcode(string file) {
FILE* sf; //executable file
FILE* f; //shellcode.h
int i, c;
const char* arr_name;
sf = fopen(file.c_str(), "rb");
if (sf == NULL) {
fprintf(stderr, "fopen(%s) Failed. Could'nt open file.", file.c_str());
return 1;
}
arr_name = "shellcode";
f = fopen("shellcode.h", "w");
fprintf(f, "unsigned char %s[] = {", arr_name);
for (i = 0;; i++) { //grab the shellcode and drop it in
if ((c = fgetc(sf)) == EOF) break; //shellcode.h
if (i != 0) fprintf(f, ",");
if ((i % 12) == 0) fprintf(f, "\n\t");
fprintf(f, "0x%.2X", (unsigned char)c);
}
fprintf(f, "\n\t};\n");
fprintf(f, "const unsigned int size = %i;\n", i);
fclose(sf);
fclose(f);
return 0;
}
int main(int argc, char* argv[]) {
if (argc < 2) { //RTFM
fprintf(stderr, "Usage: %s [filepath]\n", argv[0]);
return 1;
}
crypto(argv[1]); //cipher
cout << "Finished Ciphering " << endl;
shellcode(argv[1]); //generate shellcode
cout << "Finished Generating " << argv[1] << endl;
system("pause"); //press any key to continue
return 0;
}
Stub:
#include <Windows.h>
#include "shellcode.h" /*load up your programs shellcode*/
#include <stdint.h>
#include <stdio.h>
unsigned int key[4] = { 0xBB8,0xFA0,0x1388,0x1B58 }; /* Chose a password in hex */
#define BLOCK_SIZE 8 /* Make sure you change both */
/* xtea.cpp and stub.cpp */
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
int main() {
unsigned char shellcode_decrypted[size]; //Make a slot for your shellcode
int n_blocks = size / BLOCK_SIZE;
if (size % BLOCK_SIZE != 0) //pad the shellcode
++n_blocks;
unsigned char data[BLOCK_SIZE];
for (int i = 0; i < n_blocks; i++) {
memcpy(&data, &shellcode[i * BLOCK_SIZE], BLOCK_SIZE); //copy the shellcode into the data buffer
decipher(32, (uint32_t*)data, key); //de-xtea it
for (int j = 0; j < BLOCK_SIZE; j++)
memcpy(&shellcode_decrypted[(i * BLOCK_SIZE) + j], &data[j], sizeof(unsigned char));
memset(data, 0, BLOCK_SIZE);
}
FILE* file = fopen("C:\\Original.exe", "wb");
fwrite(shellcode_decrypted, 1, size, file);
fclose(file);
return 0;
}
Continue reading...