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

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



Представьте себе, вам необходимо доработать некую очень полезную программу без 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
Источник: habr.com
К списку статей
Опубликовано: 17.06.2020 22:05:08
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Ненормальное программирование

Pdb

Dia sdk

C++ hacks

Категории

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

  • Имя: Макс
    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