136 lines
5.1 KiB
C++
136 lines
5.1 KiB
C++
/*
|
|
* This example shows how to create a PE object file for Windows
|
|
*
|
|
* Instructions:
|
|
* 1. Compile and link this file with the COFFI library
|
|
* g++ write_obj.cpp -o writer_obj.exe
|
|
* 2. Execute the result file write_obj.exe
|
|
* write_obj.exe
|
|
* It will produce answer.o
|
|
* 3. Link the output file answer.o, with a test program
|
|
* gcc answer.o answer_test.c -o answer.exe
|
|
* 4. Run the result file:
|
|
* answer.exe
|
|
* It should print "The answer is 42"
|
|
*/
|
|
|
|
#include <string>
|
|
#include <coffi/coffi.hpp>
|
|
|
|
using namespace COFFI;
|
|
|
|
void write_the_file(const std::string& filename)
|
|
{
|
|
coffi writer;
|
|
|
|
// You can't proceed before this function call!
|
|
writer.create(COFFI_ARCHITECTURE_PE);
|
|
|
|
writer.get_header()->set_flags(IMAGE_FILE_32BIT_MACHINE |
|
|
IMAGE_FILE_LINE_NUMS_STRIPPED);
|
|
|
|
// Create code section
|
|
section* text_sec = writer.add_section(".text");
|
|
// Code that returns 42
|
|
char text[] = {
|
|
'\x55', // push %ebp
|
|
'\x89', '\xE5', // mov %esp,%ebp
|
|
'\x83', '\xE4', '\xF0', // and $0xfffffff0,%esp
|
|
'\xE8', '\x00', '\x00', '\x00', '\x00', // call b <_main+0xb>
|
|
'\xB8', '\x2A', '\x00', '\x00', '\x00', // mov $0x2a,%eax
|
|
'\xC9', // leave
|
|
'\xC3', // ret
|
|
'\x90', // nop
|
|
'\x90', // nop
|
|
};
|
|
text_sec->set_data(text, sizeof(text));
|
|
//text_sec->set_virtual_address(0x1000);
|
|
//text_sec->set_virtual_size(sizeof(text));
|
|
text_sec->set_flags(IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
|
|
IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES);
|
|
|
|
// Create a .data section, empty
|
|
section* data_sec = writer.add_section(".data");
|
|
data_sec->set_flags(IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
|
|
IMAGE_SCN_CNT_INITIALIZED_DATA |
|
|
IMAGE_SCN_ALIGN_4BYTES);
|
|
|
|
// Create a .bss section, empty
|
|
section* bss_sec = writer.add_section(".bss");
|
|
bss_sec->set_flags(IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE |
|
|
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
|
|
IMAGE_SCN_ALIGN_4BYTES);
|
|
|
|
// Create a section with arbitrary data
|
|
section* v_sec = writer.add_section(".rdata$zzz");
|
|
char v[] = "This is an arbitrary read-only string data\0";
|
|
v_sec->set_data(v, sizeof(v));
|
|
v_sec->set_flags(IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA |
|
|
IMAGE_SCN_ALIGN_4BYTES);
|
|
|
|
symbol* sym1 = writer.add_symbol(".file");
|
|
sym1->set_section_number(IMAGE_SYM_DEBUG);
|
|
sym1->set_storage_class(IMAGE_SYM_CLASS_FILE);
|
|
sym1->set_aux_symbols_number(1);
|
|
auxiliary_symbol_record_4 a1{"answer.c"};
|
|
sym1->get_auxiliary_symbols().push_back(*(auxiliary_symbol_record*)&a1);
|
|
|
|
symbol* sym2 = writer.add_symbol("_answer");
|
|
sym2->set_type(IMAGE_SYM_TYPE_FUNCTION);
|
|
sym2->set_storage_class(IMAGE_SYM_CLASS_EXTERNAL);
|
|
sym2->set_section_number(text_sec->get_index() + 1);
|
|
sym2->set_aux_symbols_number(1);
|
|
auxiliary_symbol_record a2{
|
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
|
sym2->get_auxiliary_symbols().push_back(a2);
|
|
|
|
symbol* sym3 = writer.add_symbol(".text");
|
|
sym3->set_type(IMAGE_SYM_TYPE_NOT_FUNCTION);
|
|
sym3->set_storage_class(IMAGE_SYM_CLASS_STATIC);
|
|
sym3->set_section_number(text_sec->get_index() + 1);
|
|
sym3->set_aux_symbols_number(1);
|
|
auxiliary_symbol_record_5 a3{
|
|
text_sec->get_data_size(), 1, 0, 0, 0, 0, {0, 0, 0}};
|
|
sym3->get_auxiliary_symbols().push_back(
|
|
*reinterpret_cast<auxiliary_symbol_record*>(&a3));
|
|
|
|
symbol* sym4 = writer.add_symbol(".data");
|
|
sym4->set_type(IMAGE_SYM_TYPE_NOT_FUNCTION);
|
|
sym4->set_storage_class(IMAGE_SYM_CLASS_STATIC);
|
|
sym4->set_section_number(data_sec->get_index() + 1);
|
|
sym4->set_aux_symbols_number(1);
|
|
auxiliary_symbol_record_5 a4{
|
|
data_sec->get_data_size(), 0, 0, 0, 0, 0, {0, 0, 0}};
|
|
sym4->get_auxiliary_symbols().push_back(
|
|
*reinterpret_cast<auxiliary_symbol_record*>(&a4));
|
|
|
|
symbol* sym5 = writer.add_symbol(".bss");
|
|
sym5->set_type(IMAGE_SYM_TYPE_NOT_FUNCTION);
|
|
sym5->set_storage_class(IMAGE_SYM_CLASS_STATIC);
|
|
sym5->set_section_number(bss_sec->get_index() + 1);
|
|
sym5->set_aux_symbols_number(1);
|
|
auxiliary_symbol_record_5 a5{
|
|
bss_sec->get_data_size(), 0, 0, 0, 0, 0, {0, 0, 0}};
|
|
sym5->get_auxiliary_symbols().push_back(
|
|
*reinterpret_cast<auxiliary_symbol_record*>(&a5));
|
|
|
|
symbol* sym6 = writer.add_symbol(".rdata$zzz");
|
|
sym6->set_type(IMAGE_SYM_TYPE_NOT_FUNCTION);
|
|
sym6->set_storage_class(IMAGE_SYM_CLASS_STATIC);
|
|
sym6->set_section_number(v_sec->get_index() + 1);
|
|
sym6->set_aux_symbols_number(1);
|
|
auxiliary_symbol_record_5 a6{
|
|
v_sec->get_data_size(), 0, 0, 0, 0, 0, {0, 0, 0}};
|
|
sym6->get_auxiliary_symbols().push_back(
|
|
*reinterpret_cast<auxiliary_symbol_record*>(&a6));
|
|
|
|
// Create the object file
|
|
writer.save(filename);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
write_the_file("answer.o");
|
|
return 0;
|
|
}
|