Русский
Русский
English
Статистика
Реклама

C++ hacks

PDB это не только ценный мех

17.06.2020 22:05:08 | Автор: admin


Представьте себе, вам необходимо доработать некую очень полезную программу без SDK, но по счастливому стечению обстоятельств рядом завалялся PDB файл.

(Беременным и детям не читать!)



Скажу сразу, выход есть (Ваш КО). То что комитет не в состоянии осилить десятками лет (рефлексия не нужна), ужасный M$ разработал/раздобыл 100 лет назад, а именно DIA SDK. В комплекте есть DIA2Dump.exe который порадует глаз любого художника. Остается доработать его напильником

Для начала нам нужны кошечки.

ООП баян:
#define NOINLINE __declspec(noinline)class IDrawable {public:   virtual void draw() = 0;};class Shape : public IDrawable {public:   NOINLINE Shape(int ix, int iy);   NOINLINE virtual ~Shape();   virtual void draw();   inline void setXY(int ix, int iy) { x = ix, y = iy; }   NOINLINE void someWork();   int x;   int y;};class Circle : public Shape {public:   NOINLINE Circle(int ix, int iy, int ir);   virtual ~Circle();   void draw();   int r;};Shape::Shape(int ix, int iy) { x = ix; y = iy; }Shape::~Shape() { }void Shape::someWork() { printf("someWork\n"); }void Shape::draw() { }Circle::Circle(int ix, int iy, int ir): Shape(ix, iy), r(ir) { }Circle::~Circle() { }void Circle::draw() { printf("Circle\n"); }int main(){    auto c = new Circle(0, 0, 10);    c->draw();    c->someWork();    delete c;    getchar();    return 0;}



Компилируем -> victim.exe / victim.pdb

Автор своими кривыми ручками немного доработал DIA2Dump (pdb-ripper на гитхабе, Achtung г*вн*код!!!) и теперь он выдает кое-что пригодное к использованию:

DIA2Dump.exe -rip -printCppProxy -m -g -d -rd -names "Shape;Rectangle;Circle" victim.pdb > victim.h


IDrawable
//UDT: class IDrawable @len=8 @vfcount=1//_VTable//@intro @pure @virtual vtpo=0 vfid=0 @loc=optimized @len=0 @rva=0//_Func: public void draw();//@loc=optimized @len=0 @rva=0//_Func: public void IDrawable(IDrawable * _arg0); //@loc=optimized @len=0 @rva=0//_Func: public void IDrawable(const IDrawable & _arg0); //@loc=optimized @len=0 @rva=0//_Func: public void IDrawable(); //@loc=optimized @len=0 @rva=0//_Func: public IDrawable & operator=(IDrawable * _arg0); //@loc=optimized @len=0 @rva=0//_Func: public IDrawable & operator=(const IDrawable & _arg0); //UDT;class IDrawable {public:void* _vtable;inline void draw() { typedef void (IDrawable::*_fpt)(); auto _f=xcast<_fpt>(get_vfp(this, 0)); return (this->*_f)(); }inline IDrawable * ctor() { return this; }inline void dtor() {}};



Shape
//UDT: class Shape @len=16 @vfcount=2//_Base: class IDrawable @off=0 @len=8//@loc=optimized @len=0 @rva=0//_Func: public void Shape(const Shape & _arg0); //@loc=static @len=20 @rva=4208//_Func: public void Shape(int ix, int iy); //@intro @virtual vtpo=0 vfid=1 @loc=static @len=11 @rva=4304//_Func: public void ~Shape(); //@virtual vtpo=0 vfid=0 @loc=static @len=3 @rva=4336//_Func: public void draw(); //@loc=optimized @len=0 @rva=0//_Func: public void setXY(int _arg0, int _arg1); //@loc=static @len=12 @rva=4320//_Func: public void someWork(); //@loc=optimized @len=0 @rva=0//_Func: public Shape & operator=(const Shape & _arg0); //@intro @virtual vtpo=0 vfid=1 @loc=optimized @len=0 @rva=0//_Func: public void * __vecDelDtor(unsigned int _arg0); //_Data: this+0x8, Member, Type: int, x//_Data: this+0xC, Member, Type: int, y//UDT;class Shape : public IDrawable {public:int x;int y;inline Shape * ctor(int ix, int iy) { typedef Shape * (Shape::*_fpt)(int, int); auto _f=xcast<_fpt>(_drva(4208)); return (this->*_f)(ix, iy); }inline void dtor() { typedef void (Shape::*_fpt)(); auto _f=xcast<_fpt>(get_vfp(this, 1)); (this->*_f)(); }inline void draw_impl() { typedef void (Shape::*_fpt)(); auto _f=xcast<_fpt>(_drva(4336)); return (this->*_f)(); }inline void draw() { typedef void (Shape::*_fpt)(); auto _f=xcast<_fpt>(get_vfp(this, 0)); return (this->*_f)(); }inline void someWork() { typedef void (Shape::*_fpt)(); auto _f=xcast<_fpt>(_drva(4320)); return (this->*_f)(); }};



Circle
//UDT: class Circle @len=24 @vfcount=2//_Base: class Shape @off=0 @len=16//@loc=optimized @len=0 @rva=0//_Func: public void Circle(const Circle & _arg0); //@loc=static @len=34 @rva=4352//_Func: public void Circle(int ix, int iy, int ir); //@virtual vtpo=0 vfid=1 @loc=optimized @len=0 @rva=0//_Func: public void ~Circle(); //@virtual vtpo=0 vfid=0 @loc=static @len=12 @rva=4464//_Func: public void draw(); //@loc=optimized @len=0 @rva=0//_Func: public Circle & operator=(const Circle & _arg0); //@intro @virtual vtpo=0 vfid=1 @loc=optimized @len=0 @rva=0//_Func: public void * __vecDelDtor(unsigned int _arg0); //_Data: this+0x10, Member, Type: int, r//UDT;class Circle : public Shape {public:int r;inline Circle * ctor(int ix, int iy, int ir) { typedef Circle * (Circle::*_fpt)(int, int, int); auto _f=xcast<_fpt>(_drva(4352)); return (this->*_f)(ix, iy, ir); }inline void dtor() { typedef void (Circle::*_fpt)(); auto _f=xcast<_fpt>(get_vfp(this, 1)); (this->*_f)(); }inline void draw_impl() { typedef void (Circle::*_fpt)(); auto _f=xcast<_fpt>(_drva(4464)); return (this->*_f)(); }inline void draw() { typedef void (Circle::*_fpt)(); auto _f=xcast<_fpt>(get_vfp(this, 0)); return (this->*_f)(); }};



Что тут интересного?

//UDT: class IDrawable @len=8 @vfcount=1//@intro @pure @virtual vtpo=0 vfid=0 @loc=optimized @len=0 @rva=0//_Func: public void draw();// @intro --> introducing virtual function (метод объявлен впервые)// @pure virtual --> очевидно// @vtpo --> virtual table pointer offset (крестопроблемы, может быть несколько VT)// @vfid --> virtual function id in VT// @loc=optimized --> вырезано за ненадобностью// @rva=0 --> relative virtual address


В случае вызова виртуального метода все просто, адрес уже лежит в таблице по индексу метода:

class IDrawable {// без VT никудаvoid* _vtable;// this->_vtable[func_id]()inline void draw() { typedef void (IDrawable::*_fpt)();auto _f=xcast<_fpt>(get_vfp(this, 0)); return (this->*_f)(); }};// THIS IS SPARTA!!!__forceinline void* get_vtp(void* obj) { return *((void**)obj); }__forceinline void* get_vfp(void* obj, size_t id) { return *((void**)((uint8_t*)get_vtp(obj) + id * sizeof(void*))); }


Для невиртуальных методов необходимо извлечь RVA из PDB файла и ткнуть носом компилятор:

//UDT: class Shape @len=16 @vfcount=2//@loc=optimized @len=0 @rva=0 <--- тут ничего не выгорит, компилятор заинлайнил метод//_Func: public void setXY(int _arg0, int _arg1); //@loc=static @len=12 @rva=4320 <--- ВОТ ОН, ЗДОРОВЕННЙ ЯЗЬ//_Func: public void someWork(); class Shape : public IDrawable {inline void someWork() { typedef void (Shape::*_fpt)(); auto _f=xcast<_fpt>(_drva(4320)); return (this->*_f)(); }};


Что такое _drva? Мы знаем только RVA (смещение) функции относительно базы, а нужен полноценный виртуальный адрес:

void* _image_base = GetModuleHandleA(nullptr); // hello DYNAMICBASE__forceinline void* _drva(size_t off) { return ((uint8_t*)_image_base) + off; }


Зачем xcast? Методы в плюсах вызываются по __thiscall и необходимо доступно объяснить компилятору кто тут самый умный. По факту кастуем void* в указатель на метод, this передается скрыто первым параметром:

typedef void (Shape::*_fpt)(); auto _f=xcast<_fpt>(_drva(4320)); (this->*_f)();// NUCLEAR MINEFIELD!!!template<typename TOUT, typename TIN>__forceinline TOUT xcast(TIN in){    union    {        TIN in;        TOUT out;    }    u = { in };    return u.out;}


Далее нужно внедрить наш собственный код в процесс victim.exe используя стандартные техники которые тут обсуждаться не будут. Смысл один некий код будет выполнен в адресном пространстве victim.exe.

void injected_func() {void* _image_base = GetModuleHandleA(nullptr);Circle* obj = (Circle*)malloc(sizeof(Circle));obj->ctor(0, 0, 999);((IDrawable*)obj)->draw();obj->dtor();free(obj);}


Остается хукнуть удобный метод/функцию где есть доступ к нужным объектам Или найти глобальные переменные :D

PROFIT

===

Как эта фигня используется в реальности:

Z2l0aHViLmNvbS93b25nZmVpL2FjLXBsdWdpbg==

aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1SZUg1U0tmUEtTOA==

Далее автор упоролся по хардкору и решил не просто доработать некую очень полезную программу, а отреверсить ее полностью :D
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru