-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpacker_protection.cc
More file actions
113 lines (91 loc) · 3.77 KB
/
packer_protection.cc
File metadata and controls
113 lines (91 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "packer_protection.hh"
#include "dispatcher/unpack_dispatcher.h"
extern "C" {
#include "payload/encryption.h"
}
packer::packer(elf_file *elf, elf_file *payload, std::tuple<uint8_t *, std::vector<uint8_t> &, uint64_t> marker, bool encryption)
: target(elf)
, payload(payload)
, marker(marker)
, encryption(encryption)
{
}
packer::~packer()
{
}
void
packer::apply()
{
auto &[src_marker, text_data, sh_addr] = marker;
auto unpacked_code_start {src_marker + 12 + 5};
auto pie_symbols {payload->get_symbols()};
auto payload_text {target->get_segment(*target->get_section_by_name(".elfprotext"))};
auto dispatcher_seg = target->get_segment_by_id(target->get_custom_segments().back().hdr_id);
auto &dispatcher_data {*target->get_custom_segment_data(dispatcher_seg)};
auto align_symbols = [](std::map<std::string, uint64_t> &symbols, int64_t shift) -> void {
for (auto &[name, value] : symbols)
value += shift;
};
align_symbols(pie_symbols, payload_text->p_vaddr - payload->sections_segment[payload->get_section_by_name(".text")]->p_offset);
int32_t *jmp_off = (int32_t *)((uint64_t)src_marker + 12 + 1); // marker_len + addr off in rel32 jmp
uint8_t *hide_marker = (uint8_t *)src_marker;
while (*(uint32_t *)hide_marker != HIDDEN_CODE_END)
++hide_marker;
*(uint32_t *)hide_marker = 0x90909090;
auto call_ret_addr = dispatcher_seg->p_vaddr + (uint64_t)dispatcher_data.size() + 0x36 + 12;
std::vector<uint8_t> unpacked_data;
for (uint8_t *p = src_marker + 17; p < hide_marker; ++p)
unpacked_data.push_back(*p);
std::cout << "Selected code size: " << unpacked_data.size() << "B\n";
mz_ulong cmp_len = compressBound(unpacked_data.size());
std::vector<uint8_t> packed_data(cmp_len);
int cmp_status = compress(packed_data.data(), &cmp_len, (const unsigned char *)unpacked_data.data(), unpacked_data.size());
if (cmp_status != Z_OK) {
std::cerr << "ERROR: Failed to compress code\n";
return;
}
if (cmp_len < packed_data.size())
packed_data.resize(cmp_len);
if (encryption)
encrypt(packed_data.data(), unpacked_data.size(), cmp_len);
// overwrite orginal code with random data
for (uint8_t *p = src_marker + 17; p < hide_marker; ++p)
*p = (uint8_t)(rand() % 255);
*(int32_t *)((uint8_t *)hide_marker + 5) = unpacked_data.size(); // erase_len
// JMP to shellcode
*jmp_off = (dispatcher_seg->p_vaddr + dispatcher_data.size()) - (sh_addr + ((uint64_t)src_marker - (uint64_t)&text_data[0]) + 17);
struct _unpack_dispatcher {
char _pad0[35];
int32_t dst_off;
char _pad1[3];
int8_t src_off;
char _pad2[3];
uint32_t unpacked_len;
char _pad3[7];
uint32_t packed_len;
char _pad4;
int32_t unpack_rel_addr;
char _pad5[25];
int32_t jmp_back_rel_addr;
} __attribute__((packed));
struct _unpack_dispatcher *payload = (struct _unpack_dispatcher *)unpack_dispatcher;
uint64_t rel_dst_code = (dispatcher_seg->p_vaddr + dispatcher_data.size() + 0x1c)
- (sh_addr + ((uint64_t)src_marker - (uint64_t)&text_data[0]) + 0x11);
payload->dst_off = -rel_dst_code;
payload->unpacked_len = unpacked_data.size();
payload->packed_len = cmp_len;
int32_t unpack_addr {(int32_t)pie_symbols[(encryption ? "unpack_decrypt_code" : "unpack_code")]};
payload->unpack_rel_addr = (int32_t)unpack_addr - (int32_t)call_ret_addr;
payload->jmp_back_rel_addr = (sh_addr + ((uint64_t)unpacked_code_start - (uint64_t)&text_data[0]))
- (dispatcher_seg->p_vaddr + dispatcher_data.size() + unpack_dispatcher_len);
dispatcher_seg->p_filesz += unpack_dispatcher_len;
dispatcher_seg->p_memsz += unpack_dispatcher_len;
for (size_t i = 0; i < unpack_dispatcher_len; ++i) {
dispatcher_data.push_back(unpack_dispatcher[i]);
}
dispatcher_seg->p_filesz += cmp_len;
dispatcher_seg->p_memsz += cmp_len;
for (size_t i = 0; i < cmp_len; ++i) {
dispatcher_data.push_back(packed_data[i]);
}
}