Skip to content

Commit fa125c7

Browse files
committed
[FEATURE] More precise check for TLS callbacks
1 parent 71b9a70 commit fa125c7

1 file changed

Lines changed: 67 additions & 8 deletions

File tree

pe2shc/main.cpp

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,33 @@ BYTE* shellcodify(BYTE *my_exe, size_t exe_size, size_t &out_size, bool is64b)
5353
return ext_buf;
5454
}
5555

56+
template <typename IMAGE_TLS_DIRECTORY>
57+
bool has_tls_callbacks(BYTE *my_exe, size_t exe_size)
58+
{
59+
IMAGE_DATA_DIRECTORY* tls_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
60+
if (!tls_dir) return false;
61+
62+
IMAGE_TLS_DIRECTORY* tls = peconv::get_type_directory<IMAGE_TLS_DIRECTORY>((HMODULE)my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
63+
if (!tls) return false;
64+
65+
ULONGLONG base = peconv::get_image_base(my_exe);
66+
ULONGLONG callback_rva = tls->AddressOfCallBacks;
67+
if (callback_rva > base) {
68+
callback_rva -= base;
69+
}
70+
if (!peconv::validate_ptr(my_exe, exe_size, my_exe + callback_rva, sizeof(ULONGLONG))) {
71+
return false;
72+
}
73+
ULONGLONG *callback_addr = (ULONGLONG *)(my_exe + callback_rva);
74+
if (callback_addr == 0) {
75+
return false;
76+
}
77+
if (*callback_addr == 0) {
78+
return false;
79+
}
80+
return true;
81+
}
82+
5683
bool is_supported_pe(BYTE *my_exe, size_t exe_size)
5784
{
5885
if (!my_exe) return false;
@@ -70,7 +97,40 @@ bool is_supported_pe(BYTE *my_exe, size_t exe_size)
7097
}
7198
IMAGE_DATA_DIRECTORY* tls_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
7299
if (tls_dir) {
73-
std::cout << "[WARNING] This application may have TLS callbacks, which are not supported!" << std::endl;
100+
bool has_callback = false;
101+
if (!peconv::is64bit(my_exe)) {
102+
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY32>(my_exe, exe_size)) {
103+
has_callback = true;
104+
}
105+
}
106+
else {
107+
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY64>(my_exe, exe_size)) {
108+
has_callback = true;
109+
}
110+
}
111+
if (has_callback) {
112+
std::cout << "[WARNING] This application has TLS callbacks, which are not supported!" << std::endl;
113+
}
114+
}
115+
return true;
116+
}
117+
118+
bool is_supported_pe(const std::string &in_path)
119+
{
120+
std::cout << "Reading module from: " << in_path << std::endl;
121+
size_t exe_size = 0;
122+
BYTE *my_exe = peconv::load_pe_module(in_path.c_str(), exe_size, false, false);
123+
if (!my_exe) {
124+
std::cout << "[-] Could not read the input file!" << std::endl;
125+
return false;
126+
}
127+
128+
bool is_ok = is_supported_pe(my_exe, exe_size);
129+
peconv::free_pe_buffer(my_exe);
130+
131+
if (!is_ok) {
132+
std::cout << "[-] Not supported input file!" << std::endl;
133+
return false;
74134
}
75135
return true;
76136
}
@@ -93,24 +153,23 @@ int main(int argc, char *argv[])
93153
return 0;
94154
}
95155

96-
size_t exe_size = 0;
97156
std::string in_path = argv[1];
98157
std::string out_str = make_out_name(in_path);
99158
if (argc > 2) {
100159
out_str = argv[2];
101160
}
102161

103-
std::cout << "Reading module from: " << in_path << std::endl;
162+
if (!is_supported_pe(in_path)) {
163+
return -2;
164+
}
165+
166+
size_t exe_size = 0;
104167
BYTE *my_exe = peconv::load_file(in_path.c_str(), exe_size);
105168
if (!my_exe) {
106169
std::cout << "[-] Could not read the input file!" << std::endl;
107170
return -1;
108171
}
109-
if (!is_supported_pe(my_exe, exe_size)) {
110-
std::cout << "[-] Not supported input file!" << std::endl;
111-
peconv::free_file(my_exe);
112-
return -2;
113-
}
172+
114173
bool is64b = peconv::is64bit(my_exe);
115174
size_t ext_size = 0;
116175
BYTE *ext_buf = shellcodify(my_exe, exe_size, ext_size, is64b);

0 commit comments

Comments
 (0)