cpp20 shellcode crafter

R7flex

Banned
Katılım
7 Haz 2020
Mesajlar
3,505
Beğeniler
2,000
Bu kullanıcıyla herhangi bir iş veya ticaret yapmak istiyorsanız, forumdan uzaklaştırıldığını sakın unutmayın.
R7flex Assembly Builder
@waryin dostum assembly yazarken krize giriyordu dakika başı instructionlara
bakıyordu sürekli
sitesine girip sürekli
uğraşıp duruyordu bende basit yolunu geliştirdim basit bir şekilde instructionları kullanıp
her türlü alanda işe yarıcak bir proje oldu tamamen cpp17 ile gelip cpp20'de büyük değişiklere uğratılan
std::holds_alternative, std::variant kullanıldı bize büyük ölçüde kolaylık sağlıyor.
ek olarak deprecated type ve templateler sayesinde yine cpp17 desteğide vardır (cpp14 ve altı çalışmaz)


Main Instruction Destekleri:
mov, call, push, pop, ret (çok istiyorsanız daha şeyler siz ekleyin banane)
image.png


image.png

Örnek Kullanım:
C++:
#include <iostream>
#include <iomanip>
#include <windows.h>

#include "assembly_builder.hpp"
using namespace shellcode;

void example_function() {
    std::cout << "huso niye facebook oldun" << std::endl;
}

int32_t main() {
    {
        shellcode::assemby_builder builder;

        builder
            .add(assembly_instruction::x64_type::MOV, { assembly_instruction::x64_register::RAX, &example_function })
            .add(assembly_instruction::x64_type::CALL, { assembly_instruction::x64_register::RAX })
            .add(assembly_instruction::x64_type::RET);

        auto shellcode = builder.build();

        std::cout << "generated func shell:" << std::endl;
        for (auto byte : shellcode) {
            std::cout << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
        }
        std::cout << std::endl;

        void* exec_mem = VirtualAlloc(nullptr, shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!exec_mem) {
            return 1;
        }

        std::copy(shellcode.begin(), shellcode.end(), static_cast<std::uint8_t*>(exec_mem));

        std::cout << "running shell..." << std::endl;
        try {
            using shellcode_test = void(*)();
            auto func = reinterpret_cast<shellcode_test>(exec_mem);
            func();
        }
        catch (...) {
            std::cerr << "error" << std::endl;
        }

        if (exec_mem) {
            VirtualFree(exec_mem, 0, MEM_RELEASE);
        }
    }

    return 1337;
}
 
Son düzenleme:
Bu kullanıcıyla herhangi bir iş veya ticaret yapmak istiyorsanız, forumdan uzaklaştırıldığını sakın unutmayın.
bu get_register_code arrayi yanlis degil mi la rax 0x48 rcx 0x49 falan yazmis ama bunlar register kodu degil rex prefix kodu aq

(begenmedim)
kardeş ai'ya atıp rex prefixi öğretme bana
rex prefix diyor hala bana çıldırırısın ai'ya atmış kodda hata var mı diye :p :p :p
3 tane hold statesi var orda esek

image.png
 
weller ve sems ilgisi ve yardımı icin tesekkur ederim

bazi arkadaslarin bu bilgiler yararina veya ogrenmesine yardimci olabilir, eger yanlisim var isede duzeltebilirisiniz.
bu arada hic bir yazimda ai kullanmadim kaynak atabilirsin, dm'den soru sordugumda cevapladigin icin tesekkur ederim.
assembly_builder.hpp:
C++:
// enum sirasi intel dokumantasyonuna gore yanlis 
// rax rcx rdx rbx olmali ama kodda:

enum class x64_register {
    RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP,
    R8, R9, R10, R11, R12, R13, R14, R15
};

C++:
// get_register_code arrayinde register kodlari yerine rex prefix kodlari kullanmis:

constexpr std::array<std::uint8_t, 16> reg_codes = {
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
};

C++:
// generate_mov fonksiyonunda modrm byte olusturmuyor:

if (std::holds_alternative<assembly_instruction::x64_register>(src)) {
    auto src_reg = std::get<assembly_instruction::x64_register>(src);
    auto code = std::array{ 0x48, 0x89 };
    shellcode.insert(shellcode.end(), code.begin(), code.end());
    shellcode.push_back(get_register_code(src_reg)[0]);
    shellcode.push_back(get_register_code(dest_reg)[0]);
}

rex prefixleri modrm bytelari hic dogru kullanmamis
mov kisminda sabit 0x48 rex prefix kullandigi icin r8-r15 registerlarini kullanamaz
call kisminda da rex prefix kullanmadigi icin r8-r15 ile call yapilamaz
adresten registera okuma yaptigindan bazi durumlarda calismis ama register-register islemler kesinlikle calismaz

dm'den dedigine baktigimizda:
"rex prefixleri (0x48-0x4F) zaten 64bit operasyonlar için gerekli yanlış register kodları kullanılsa da sonuçta doğru byte oluşuyor CPU bu byteları yine de doğru şekilde yorumluyor"

rex prefixler (0x40-0x4f) ile register kodlari (0-15) tamamen farkli kavramlardir kodda register kodlari yerine rex prefixleri kullanmis modrm byte olusturmadan dogru assembly kod uretilemez intel manuele gore register encoding'de rax=0 rcx=1 rdx=2 rbx=3 seklinde gider

attigin resime gelirsek:
resimde instruction formati acikca gosteriliyor instructionlar 48 89 f2 seklinde hex kodlari ile ayri ayri gosteriliyor 48 = rex.w prefix 89 = mov opcode f2 = register encoding (rsi rdx) bu 3 byte beraber mov rdx rsi yapar resim rex prefix ile register encoding kavraminin farkli oldugunu gosteriyor

kaynaklar:
1 intel 64 ve ia-32:
2 x86-64 instruction encoding:
3 x86 ve amd64 instruction reference:
4 modr/m ve sib byte encoding:
 
Bu kullanıcıyla herhangi bir iş veya ticaret yapmak istiyorsanız, forumdan uzaklaştırıldığını sakın unutmayın.
weller ve sems ilgisi ve yardımı icin tesekkur ederim

bazi arkadaslarin bu bilgiler yararina veya ogrenmesine yardimci olabilir, eger yanlisim var isede duzeltebilirisiniz.
bu arada hic bir yazimda ai kullanmadim kaynak atabilirsin, dm'den soru sordugumda cevapladigin icin tesekkur ederim.
assembly_builder.hpp:
C++:
// enum sirasi intel dokumantasyonuna gore yanlis
// rax rcx rdx rbx olmali ama kodda:

enum class x64_register {
    RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP,
    R8, R9, R10, R11, R12, R13, R14, R15
};

C++:
// get_register_code arrayinde register kodlari yerine rex prefix kodlari kullanmis:

constexpr std::array<std::uint8_t, 16> reg_codes = {
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
};

C++:
// generate_mov fonksiyonunda modrm byte olusturmuyor:

if (std::holds_alternative<assembly_instruction::x64_register>(src)) {
    auto src_reg = std::get<assembly_instruction::x64_register>(src);
    auto code = std::array{ 0x48, 0x89 };
    shellcode.insert(shellcode.end(), code.begin(), code.end());
    shellcode.push_back(get_register_code(src_reg)[0]);
    shellcode.push_back(get_register_code(dest_reg)[0]);
}

rex prefixleri modrm bytelari hic dogru kullanmamis
mov kisminda sabit 0x48 rex prefix kullandigi icin r8-r15 registerlarini kullanamaz
call kisminda da rex prefix kullanmadigi icin r8-r15 ile call yapilamaz
adresten registera okuma yaptigindan bazi durumlarda calismis ama register-register islemler kesinlikle calismaz

dm'den dedigine baktigimizda:
"rex prefixleri (0x48-0x4F) zaten 64bit operasyonlar için gerekli yanlış register kodları kullanılsa da sonuçta doğru byte oluşuyor CPU bu byteları yine de doğru şekilde yorumluyor"

rex prefixler (0x40-0x4f) ile register kodlari (0-15) tamamen farkli kavramlardir kodda register kodlari yerine rex prefixleri kullanmis modrm byte olusturmadan dogru assembly kod uretilemez intel manuele gore register encoding'de rax=0 rcx=1 rdx=2 rbx=3 seklinde gider

attigin resime gelirsek:
resimde instruction formati acikca gosteriliyor instructionlar 48 89 f2 seklinde hex kodlari ile ayri ayri gosteriliyor 48 = rex.w prefix 89 = mov opcode f2 = register encoding (rsi rdx) bu 3 byte beraber mov rdx rsi yapar resim rex prefix ile register encoding kavraminin farkli oldugunu gosteriyor

kaynaklar:
1 intel 64 ve ia-32:
2 x86-64 instruction encoding:
3 x86 ve amd64 instruction reference:
4 modr/m ve sib byte encoding:
komplike assemblyi hiç bir zaman kullanmıcaz maksimum hook için
 
Bu kullanıcıyla herhangi bir iş veya ticaret yapmak istiyorsanız, forumdan uzaklaştırıldığını sakın unutmayın.
weller ve sems ilgisi ve yardımı icin tesekkur ederim

bazi arkadaslarin bu bilgiler yararina veya ogrenmesine yardimci olabilir, eger yanlisim var isede duzeltebilirisiniz.
bu arada hic bir yazimda ai kullanmadim kaynak atabilirsin, dm'den soru sordugumda cevapladigin icin tesekkur ederim.
assembly_builder.hpp:
C++:
// enum sirasi intel dokumantasyonuna gore yanlis
// rax rcx rdx rbx olmali ama kodda:

enum class x64_register {
    RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP,
    R8, R9, R10, R11, R12, R13, R14, R15
};

C++:
// get_register_code arrayinde register kodlari yerine rex prefix kodlari kullanmis:

constexpr std::array<std::uint8_t, 16> reg_codes = {
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
};

C++:
// generate_mov fonksiyonunda modrm byte olusturmuyor:

if (std::holds_alternative<assembly_instruction::x64_register>(src)) {
    auto src_reg = std::get<assembly_instruction::x64_register>(src);
    auto code = std::array{ 0x48, 0x89 };
    shellcode.insert(shellcode.end(), code.begin(), code.end());
    shellcode.push_back(get_register_code(src_reg)[0]);
    shellcode.push_back(get_register_code(dest_reg)[0]);
}

rex prefixleri modrm bytelari hic dogru kullanmamis
mov kisminda sabit 0x48 rex prefix kullandigi icin r8-r15 registerlarini kullanamaz
call kisminda da rex prefix kullanmadigi icin r8-r15 ile call yapilamaz
adresten registera okuma yaptigindan bazi durumlarda calismis ama register-register islemler kesinlikle calismaz

dm'den dedigine baktigimizda:
"rex prefixleri (0x48-0x4F) zaten 64bit operasyonlar için gerekli yanlış register kodları kullanılsa da sonuçta doğru byte oluşuyor CPU bu byteları yine de doğru şekilde yorumluyor"

rex prefixler (0x40-0x4f) ile register kodlari (0-15) tamamen farkli kavramlardir kodda register kodlari yerine rex prefixleri kullanmis modrm byte olusturmadan dogru assembly kod uretilemez intel manuele gore register encoding'de rax=0 rcx=1 rdx=2 rbx=3 seklinde gider

attigin resime gelirsek:
resimde instruction formati acikca gosteriliyor instructionlar 48 89 f2 seklinde hex kodlari ile ayri ayri gosteriliyor 48 = rex.w prefix 89 = mov opcode f2 = register encoding (rsi rdx) bu 3 byte beraber mov rdx rsi yapar resim rex prefix ile register encoding kavraminin farkli oldugunu gosteriyor

kaynaklar:
1 intel 64 ve ia-32:
2 x86-64 instruction encoding:
3 x86 ve amd64 instruction reference:
4 modr/m ve sib byte encoding:
yeni okudum cok beles ai write'a benziyor

eğer sadece 0x48 gibi sabit prefix kullanılıyorsa
r8 ve türevi üst registerlara erişilmez

modrm ve rex.r/b/x bitleri doğru ayarlanmamışsa adres üzerinden etkileşimlerde tanımsız davranışa girsede kendisini düzelticektir iyi günler 2000lerde değiliz 2025teyiz ve sadece ia32 ye göre hareket etmeyiz
 
Bu kullanıcıyla herhangi bir iş veya ticaret yapmak istiyorsanız, forumdan uzaklaştırıldığını sakın unutmayın.
R7flex Assembly Builder
@waryin dostum assembly yazarken krize giriyordu dakika başı instructionlara
bakıyordu sürekli
sitesine girip sürekli
uğraşıp duruyordu bende basit yolunu geliştirdim basit bir şekilde instructionları kullanıp
her türlü alanda işe yarıcak bir proje oldu tamamen cpp17 ile gelip cpp20'de büyük değişiklere uğratılan
std::holds_alternative, std::variant kullanıldı bize büyük ölçüde kolaylık sağlıyor.
ek olarak deprecated type ve templateler sayesinde yine cpp17 desteğide vardır (cpp14 ve altı çalışmaz)


Main Instruction Destekleri:
mov, call, ret (çok istiyorsanız daha şeyler siz ekleyin banane)
image.png


image.png

Örnek Kullanım:
C++:
#include <iostream>
#include <iomanip>
#include <windows.h>

#include "assembly_builder.hpp"
using namespace shellcode;

void example_function() {
    std::cout << "huso niye facebook oldun" << std::endl;
}

int32_t main() {
    {
        shellcode::assemby_builder builder;

        builder
            .add(assembly_instruction::x64_type::MOV, { assembly_instruction::x64_register::RAX, &example_function })
            .add(assembly_instruction::x64_type::CALL, { assembly_instruction::x64_register::RAX })
            .add(assembly_instruction::x64_type::RET);

        auto shellcode = builder.build();

        std::cout << "generated func shell:" << std::endl;
        for (auto byte : shellcode) {
            std::cout << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
        }
        std::cout << std::endl;

        void* exec_mem = VirtualAlloc(nullptr, shellcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!exec_mem) {
            return 1;
        }

        std::copy(shellcode.begin(), shellcode.end(), static_cast<std::uint8_t*>(exec_mem));

        std::cout << "running shell..." << std::endl;
        try {
            using shellcode_test = void(*)();
            auto func = reinterpret_cast<shellcode_test>(exec_mem);
            func();
        }
        catch (...) {
            std::cerr << "error" << std::endl;
        }

        if (exec_mem) {
            VirtualFree(exec_mem, 0, MEM_RELEASE);
        }
    }

    return 1337;
}
aslan kardeşim mesajını aldım Elbet bir gün 🕊️🕊️
 
Bu kullanıcıyla herhangi bir iş veya ticaret yapmak istiyorsanız, forumdan uzaklaştırıldığını sakın unutmayın.
R7flex eline sağlık çok güzel olmuş ama sakın birdaha yapma (!)
 

Şuanda konuyu görüntüleyen kullanıcılar

Geri
Üst Alt