• XSS.stack #1 – первый литературный журнал от юзеров форума

Вкат в С, С+

Пожалуйста, обратите внимание, что пользователь заблокирован
Если чисто сишный, то buhtrap
Так а где исходники брать? Вот это: https://github.com/RomaniukVadim/hack_scripts/tree/master/Dark soft/Buhtrap Source Code/ ?

И к чему он пришел, без понимания основ?
Так а как тот факт, что он тупой и не учится, зависит от Петухонов и Шарпов? Дело в человеке, а не в инструментах.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так а где исходники брать?
Да, это оно. А так, все есть на гитхабе. https://github.com/Aekras1a/Updated-Carbanak-Source-with-Plugins

зависит от Петухонов и Шарпов?
Мы с тобой это уже обсуждали.
1. Чем легче язык, тем больше нубов и негодных людей может войти в сферу. Ниже порог вхождения, который с каждым годом снижается со всех сторон. В 90ые-начало 2000ых у многих не было инета, а для кодинга был хелп от 6ой студии и инклуд windows.h . И подобные люди становились той самой элитой, ибо не было выбора - или ты осилил и закодил, или ничего. А что сейчас? Чето не получается, побежал на стековерфлоу, своей работы ноль, умственных усилий тоже , один копипаст.
2. Кодинг только на высокоуровневых говноскриптах ведет к непониманию базовых принципов работы ОС и так далее. Вот тебе для примера - https://xss.pro/threads/74198/post-511291 - думаю, комментарии излишни? А если бы человек изучил винапи, он бы понимал, как и что там работает. Но увы, начиная с растов и питонов веришь в магию.
 
Да, это оно. А так, все есть на гитхабе. https://github.com/Aekras1a/Updated-Carbanak-Source-with-Plugins


Мы с тобой это уже обсуждали.
1. Чем легче язык, тем больше нубов и негодных людей может войти в сферу. Ниже порог вхождения, который с каждым годом снижается со всех сторон. В 90ые-начало 2000ых у многих не было инета, а для кодинга был хелп от 6ой студии и инклуд windows.h . И подобные люди становились той самой элитой, ибо не было выбора - или ты осилил и закодил, или ничего. А что сейчас? Чето не получается, побежал на стековерфлоу, своей работы ноль, умственных усилий тоже , один копипаст.
2. Кодинг только на высокоуровневых говноскриптах ведет к непониманию базовых принципов работы ОС и так далее. Вот тебе для примера - https://xss.pro/threads/74198/post-511291 - думаю, комментарии излишни? А если бы человек изучил винапи, он бы понимал, как и что там работает. Но увы, начиная с растов и питонов веришь в магию.
Наличие высокоуровневых абстракций в языке никак не влияет на вход в сферу. Ну есть раст, куча других языков, и это что то меняет? Обычно такие "кодеры" не уезжают дальше сказок на форумах и хелловордов, написать "что то" это одно, а вот написать "что то" качественное, приносящее деньги - совсем другое. На си можно закодить говно, далеко за примерами ходить не приходится, посмотри исходники большинства современных стиллеров, лоадеров и прочей примитивной малвары. Решает хорошее понимание windows internals, информатики, устройства операционных систем. Готов поставить сотку баксов, если ты спросишь у кого то из этих "дельцов" о чем либо из программы информатики 6 класса, ответа не получишь.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так а чего там Цэшного, кроме исходников мимикатца, которые к коду малвари имеет мало отношения. Нужен чистый и качественный Цэ код малвари, а не это жульничество с RAII и ссылками. Остальное как бы на Плюсах, включая нелюбимые Цэшниками ООП-абстракции, которых там довольно много, например:
Код:
class StringBuilder
{
    protected:

        char* ptr; //выделенная памяти для строки
        int len; //длина строки (без завершающего нуля)
        int size; //размер выделенной памяти
        bool alloc; //true - если в ptr выделенная этим классом память, будет удалятся в деструкторе, если false, то память была передана из вне и поэтому удаляться не будет

        StringBuilder( const StringBuilder& );

    public:

        //создает пустую строку и выделяет указанное количество памяти, копирует указанную строку
        explicit StringBuilder( int _size = 128, const char* s = 0, int len_s = -1 );
        //создает строку хранимую в переданной памяти, в деструкторе эта память не будет удалятся
        //если _ptr = 0, то будет браться s, т. е. создается объект без копирования строки,
        //и если _size < 0, то оно будет равно длине строке + 1 (завершающий нуль)
        explicit StringBuilder( char* _ptr, int _size, const char* s = 0, int len_s = -1 );
        //создает строку на основе переданного блока памяти, начало строки с start, если len = -1, то длина строки будет равна длине заполненной памяти
        //в блоке памяти обязательно должно быть место для завершающего нуля, так как конструктор его будет устанавливать.
        //количество выделенной памяти будет равно количеству выделенной памяти в data.
        //Внимание! data не должно уничтожиться раньше чем данная строка
        StringBuilder( Mem::Data& data, int start = 0, int _len = -1 );
        ~StringBuilder();

        //увеличивает размер выделенной памяти для строки, если нужно
        bool Grow( int addSize );
        int Len() const
        {
            return len;
        }

        int Size() const
        {
            return size;
        }

        char* c_str() const
        {
            return ptr;
        }

        operator char*() const
        {
            return c_str();
        }

        char& operator[]( int index )
        {
            return ptr[index];
        }

        StringBuilder& Cat( const char* s, int len_s = -1 );
        StringBuilder& Cat( char c );
        StringBuilder& Cat( int v, int radix = 10 );
        StringBuilder& Cat( uint v, int radix = 10 );
        StringBuilder& Copy( const char* s, int len_s = -1 );

        StringBuilder& operator+=( const char* s )
        {
            return Cat(s);
        }
        StringBuilder& operator+=( const StringBuilder& sb )
        {
            return Cat( sb.ptr, sb.len );
        }
        StringBuilder& operator+=( char c )
        {
            return Cat(c);
        }
        StringBuilder& operator+=( int v )
        {
            return Cat(v);
        }
        StringBuilder& operator+=( uint v )
        {
            return Cat(v);
        }

        StringBuilder& operator=( const char* s )
        {
            return Copy(s);
        }
        StringBuilder& operator=( const StringBuilder& sb )
        {
            return Copy( sb.ptr, sb. len );
        }

        //вычисляет длину строки, используется после использования WINAPI функций
        int UpdateLen();
        //устанавливает новую длину строки и возвращает старую
        int SetLen( int newLen );
        //делает строку пустой
        void SetEmpty()
        {
            SetLen(0);
        }
        StringBuilder& Upper()
        {
            Str::Upper(ptr);
            return *this;
        }
        StringBuilder& Lower()
        {
            Str::Lower(ptr);
            return *this;
        }
        uint Hash() const
        {
            return Str::Hash( ptr, len );
        }

        StringBuilder& Format( const char* format, ... )
        {
            va_list va;
            va_start( va, format );
            len = Str::FormatVA( ptr, format, va );
            return *this;
        }
        int Cmp( const char* s, int max = INT_MAX ) const
        {
            return Str::Cmp( ptr, s, max );
        }
        bool operator==( const char* s ) const
        {
            return Cmp(s) == 0;
        }
        bool operator==( const StringBuilder& s ) const
        {
            return Cmp( s.c_str() ) == 0;
        }
        bool operator!=( const char* s ) const
        {
            return Cmp(s) != 0;
        }
        bool operator!=( const StringBuilder& s ) const
        {
            return Cmp( s.c_str() ) != 0;
        }
        int IndexOf( int start, const char* sub, int c_sub = -1 ) const;
        int IndexOf( int start, const StringBuilder& sub ) const
        {
            return IndexOf( start, sub.ptr, sub.len );
        }
        int IndexOf( const char* sub, int c_sub = -1 ) const
        {
            return IndexOf( 0, sub, c_sub );
        }
        int IndexOf( const StringBuilder& sub ) const
        {
            return IndexOf( 0, sub );
        }
        int IndexOf( int start, char c ) const;
        int IndexOf( char c ) const
        {
            return IndexOf( 0, c );
        }

        //выделяет подстроку начиная с позиции index и длиною len
        StringBuilder& Substring( int index, int _len = INT_MAX );
        //выделяет подстроку начиная с позиции index и длиною len и ложит в s
        //возвращает s (выделенную строку)
        StringBuilder& Substring( StringBuilder& s, int index, int _len = INT_MAX ) const;
        //вставляет указанную позицию строку, если индекс больше длины строки, то вставка не будет проводится
        StringBuilder& Insert( int index, const char* s, int c_s = -1 );
        StringBuilder& Insert( int index, const StringBuilder& s )
        {
            return Insert( index, s.c_str(), s.Len() );
        }
        StringBuilder& Insert( int index, char c );
        //заменяет в строке с позиции index и sz символов на строку s
        StringBuilder& Replace( int index, int sz, const char* s, int c_s = -1 );
        StringBuilder& Replace( int index, int sz, const StringBuilder& s )
        {
            return Replace( index, sz, s.c_str(), s.Len() );
        }
        //заменить строку oldStr на newStr начиная с позиции start и n раз
        //если не указывать newStr, т. е. передавать 0, то будет удаляться строки oldStr, но только вместо 0, лучше ставить nullptr, так как из-за
        //перегружаемых функций может вызваться нета
        StringBuilder& Replace( int start, int n, const char* oldStr, const char* newStr, int c_oldStr = -1, int c_newStr = -1 );
        StringBuilder& Replace( int start, const char* oldStr, const char* newStr, int c_oldStr = -1, int c_newStr = -1 )
        {
            return Replace( start, INT_MAX, oldStr, newStr, c_oldStr, c_newStr );
        }
        StringBuilder& Replace( const char* oldStr, const char* newStr, int c_oldStr = -1, int c_newStr = -1 )
        {
            return Replace( 0, INT_MAX, oldStr, newStr, c_oldStr, c_newStr );
        }
        StringBuilder& Replace( int start, int n, const StringBuilder& oldStr, const StringBuilder& newStr )
        {
            return Replace( start, n, oldStr.c_str(), newStr.c_str(), oldStr.Len(), newStr.Len() );
        }
        StringBuilder& Replace( int start, const StringBuilder& oldStr, const StringBuilder& newStr )
        {
            return Replace( start, INT_MAX, oldStr.c_str(), newStr.c_str(), oldStr.Len(), newStr.Len() );
        }
        StringBuilder& Replace( const StringBuilder& oldStr, const StringBuilder& newStr )
        {
            return Replace( 0, INT_MAX, oldStr.c_str(), newStr.c_str(), oldStr.Len(), newStr.Len() );
        }

        int ReplaceChars( const char* olds, const char* news )
        {
            return len = Str::ReplaceChars( ptr, olds, news );
        }

        int ReplaceChar( char oldc, char newc );

        bool IsEmpty() const
        {
            if( len == 0 ) return true;
            return false;
        }
        StringArray Split( char c ) const;
        StringArray Split( const char* s, int c_s = -1 ) const;
        int ToInt( bool hex = false )
        {
            return Str::ToInt( ptr, hex );
        }
        int ToInt( int start, bool hex = false );
        StringBuilder& LTrim( char c = ' ' )
        {
            len -= Str::LTrim( ptr, c );
            return *this;
        }
        StringBuilder& RTrim( char c = ' ' )
        {
            len -= Str::RTrim( ptr, c, len );
            return *this;
        }
        StringBuilder& Trim( char c = ' ' )
        {
            len -= Str::Trim( ptr, c, len );
            return *this;
        }
        //сформировать конец строки (\r\n)
        StringBuilder& FillEndStr();
        //заполнить строку символами c, строка станет длиною count
        StringBuilder& Set( char c, int count );
        //оставляет count символов слева
        StringBuilder& Left( int count )
        {
            SetLen(len);
            return *this;
        }
        //оставляет count символов справа
        StringBuilder& Right( int count );
        //конвертирует строки unicode в win1251
        StringBuilder& ToWin1251( const wchar_t* from, int c_from = -1 );

        int Ignore( int p, char c )
        {
            return Str::Ignore( ptr, p, c );
        }
};

Чем легче язык, тем больше нубов и негодных людей может войти в сферу. Ниже порог вхождения, который с каждым годом снижается со всех сторон. В 90ые-начало 2000ых у многих не было инета, а для кодинга был хелп от 6ой студии и инклуд windows.h . И подобные люди становились той самой элитой, ибо не было выбора - или ты осилил и закодил, или ничего. А что сейчас? Чето не получается, побежал на стековерфлоу, своей работы ноль, умственных усилий тоже , один копипаст.
Ну это зависит от людей, а не от инструментов. Если человек не хочет учиться, то никакие православные Цэ его не изменят, разница будет лишь в том, что он будет продавать еще более всратую малварь, чем если бы он писал ее на Шарпах или Петухонах. Опять же на Шарпах, зная как работают внутренности фреймворка можно такой забористой бесфайлой малвари написать, что она по многим параметрам будет лучше нативной. Или на Петухонах можно легко написать скриптовый метаморф, используя встроенный модуль ast, а нативного метаморфа стабильного я не видел никогда.

Кодинг только на высокоуровневых говноскриптах ведет к непониманию базовых принципов работы ОС и так далее. Вот тебе для примера - https://xss.pro/threads/74198/post-511291 - думаю, комментарии излишни? А если бы человек изучил винапи, он бы понимал, как и что там работает. Но увы, начиная с растов и питонов веришь в магию.
Так и что бы изменилось по твоему? Он бы и на Цэ пытался загрузить 100гб в виртуальную память.
 
Так а чего там Цэшного, кроме исходников мимикатца, которые к коду малвари имеет мало отношения. Нужен чистый и качественный Цэ код малвари, а не это жульничество с RAII и ссылками. Остальное как бы на Плюсах, включая нелюбимые Цэшниками ООП-абстракции, которых там довольно много, например:
Код:
class StringBuilder
{
    protected:

        char* ptr; //выделенная памяти для строки
        int len; //длина строки (без завершающего нуля)
        int size; //размер выделенной памяти
        bool alloc; //true - если в ptr выделенная этим классом память, будет удалятся в деструкторе, если false, то память была передана из вне и поэтому удаляться не будет

        StringBuilder( const StringBuilder& );

    public:

        //создает пустую строку и выделяет указанное количество памяти, копирует указанную строку
        explicit StringBuilder( int _size = 128, const char* s = 0, int len_s = -1 );
        //создает строку хранимую в переданной памяти, в деструкторе эта память не будет удалятся
        //если _ptr = 0, то будет браться s, т. е. создается объект без копирования строки,
        //и если _size < 0, то оно будет равно длине строке + 1 (завершающий нуль)
        explicit StringBuilder( char* _ptr, int _size, const char* s = 0, int len_s = -1 );
        //создает строку на основе переданного блока памяти, начало строки с start, если len = -1, то длина строки будет равна длине заполненной памяти
        //в блоке памяти обязательно должно быть место для завершающего нуля, так как конструктор его будет устанавливать.
        //количество выделенной памяти будет равно количеству выделенной памяти в data.
        //Внимание! data не должно уничтожиться раньше чем данная строка
        StringBuilder( Mem::Data& data, int start = 0, int _len = -1 );
        ~StringBuilder();

        //увеличивает размер выделенной памяти для строки, если нужно
        bool Grow( int addSize );
        int Len() const
        {
            return len;
        }

        int Size() const
        {
            return size;
        }

        char* c_str() const
        {
            return ptr;
        }

        operator char*() const
        {
            return c_str();
        }

        char& operator[]( int index )
        {
            return ptr[index];
        }

        StringBuilder& Cat( const char* s, int len_s = -1 );
        StringBuilder& Cat( char c );
        StringBuilder& Cat( int v, int radix = 10 );
        StringBuilder& Cat( uint v, int radix = 10 );
        StringBuilder& Copy( const char* s, int len_s = -1 );

        StringBuilder& operator+=( const char* s )
        {
            return Cat(s);
        }
        StringBuilder& operator+=( const StringBuilder& sb )
        {
            return Cat( sb.ptr, sb.len );
        }
        StringBuilder& operator+=( char c )
        {
            return Cat(c);
        }
        StringBuilder& operator+=( int v )
        {
            return Cat(v);
        }
        StringBuilder& operator+=( uint v )
        {
            return Cat(v);
        }

        StringBuilder& operator=( const char* s )
        {
            return Copy(s);
        }
        StringBuilder& operator=( const StringBuilder& sb )
        {
            return Copy( sb.ptr, sb. len );
        }

        //вычисляет длину строки, используется после использования WINAPI функций
        int UpdateLen();
        //устанавливает новую длину строки и возвращает старую
        int SetLen( int newLen );
        //делает строку пустой
        void SetEmpty()
        {
            SetLen(0);
        }
        StringBuilder& Upper()
        {
            Str::Upper(ptr);
            return *this;
        }
        StringBuilder& Lower()
        {
            Str::Lower(ptr);
            return *this;
        }
        uint Hash() const
        {
            return Str::Hash( ptr, len );
        }

        StringBuilder& Format( const char* format, ... )
        {
            va_list va;
            va_start( va, format );
            len = Str::FormatVA( ptr, format, va );
            return *this;
        }
        int Cmp( const char* s, int max = INT_MAX ) const
        {
            return Str::Cmp( ptr, s, max );
        }
        bool operator==( const char* s ) const
        {
            return Cmp(s) == 0;
        }
        bool operator==( const StringBuilder& s ) const
        {
            return Cmp( s.c_str() ) == 0;
        }
        bool operator!=( const char* s ) const
        {
            return Cmp(s) != 0;
        }
        bool operator!=( const StringBuilder& s ) const
        {
            return Cmp( s.c_str() ) != 0;
        }
        int IndexOf( int start, const char* sub, int c_sub = -1 ) const;
        int IndexOf( int start, const StringBuilder& sub ) const
        {
            return IndexOf( start, sub.ptr, sub.len );
        }
        int IndexOf( const char* sub, int c_sub = -1 ) const
        {
            return IndexOf( 0, sub, c_sub );
        }
        int IndexOf( const StringBuilder& sub ) const
        {
            return IndexOf( 0, sub );
        }
        int IndexOf( int start, char c ) const;
        int IndexOf( char c ) const
        {
            return IndexOf( 0, c );
        }

        //выделяет подстроку начиная с позиции index и длиною len
        StringBuilder& Substring( int index, int _len = INT_MAX );
        //выделяет подстроку начиная с позиции index и длиною len и ложит в s
        //возвращает s (выделенную строку)
        StringBuilder& Substring( StringBuilder& s, int index, int _len = INT_MAX ) const;
        //вставляет указанную позицию строку, если индекс больше длины строки, то вставка не будет проводится
        StringBuilder& Insert( int index, const char* s, int c_s = -1 );
        StringBuilder& Insert( int index, const StringBuilder& s )
        {
            return Insert( index, s.c_str(), s.Len() );
        }
        StringBuilder& Insert( int index, char c );
        //заменяет в строке с позиции index и sz символов на строку s
        StringBuilder& Replace( int index, int sz, const char* s, int c_s = -1 );
        StringBuilder& Replace( int index, int sz, const StringBuilder& s )
        {
            return Replace( index, sz, s.c_str(), s.Len() );
        }
        //заменить строку oldStr на newStr начиная с позиции start и n раз
        //если не указывать newStr, т. е. передавать 0, то будет удаляться строки oldStr, но только вместо 0, лучше ставить nullptr, так как из-за
        //перегружаемых функций может вызваться нета
        StringBuilder& Replace( int start, int n, const char* oldStr, const char* newStr, int c_oldStr = -1, int c_newStr = -1 );
        StringBuilder& Replace( int start, const char* oldStr, const char* newStr, int c_oldStr = -1, int c_newStr = -1 )
        {
            return Replace( start, INT_MAX, oldStr, newStr, c_oldStr, c_newStr );
        }
        StringBuilder& Replace( const char* oldStr, const char* newStr, int c_oldStr = -1, int c_newStr = -1 )
        {
            return Replace( 0, INT_MAX, oldStr, newStr, c_oldStr, c_newStr );
        }
        StringBuilder& Replace( int start, int n, const StringBuilder& oldStr, const StringBuilder& newStr )
        {
            return Replace( start, n, oldStr.c_str(), newStr.c_str(), oldStr.Len(), newStr.Len() );
        }
        StringBuilder& Replace( int start, const StringBuilder& oldStr, const StringBuilder& newStr )
        {
            return Replace( start, INT_MAX, oldStr.c_str(), newStr.c_str(), oldStr.Len(), newStr.Len() );
        }
        StringBuilder& Replace( const StringBuilder& oldStr, const StringBuilder& newStr )
        {
            return Replace( 0, INT_MAX, oldStr.c_str(), newStr.c_str(), oldStr.Len(), newStr.Len() );
        }

        int ReplaceChars( const char* olds, const char* news )
        {
            return len = Str::ReplaceChars( ptr, olds, news );
        }

        int ReplaceChar( char oldc, char newc );

        bool IsEmpty() const
        {
            if( len == 0 ) return true;
            return false;
        }
        StringArray Split( char c ) const;
        StringArray Split( const char* s, int c_s = -1 ) const;
        int ToInt( bool hex = false )
        {
            return Str::ToInt( ptr, hex );
        }
        int ToInt( int start, bool hex = false );
        StringBuilder& LTrim( char c = ' ' )
        {
            len -= Str::LTrim( ptr, c );
            return *this;
        }
        StringBuilder& RTrim( char c = ' ' )
        {
            len -= Str::RTrim( ptr, c, len );
            return *this;
        }
        StringBuilder& Trim( char c = ' ' )
        {
            len -= Str::Trim( ptr, c, len );
            return *this;
        }
        //сформировать конец строки (\r\n)
        StringBuilder& FillEndStr();
        //заполнить строку символами c, строка станет длиною count
        StringBuilder& Set( char c, int count );
        //оставляет count символов слева
        StringBuilder& Left( int count )
        {
            SetLen(len);
            return *this;
        }
        //оставляет count символов справа
        StringBuilder& Right( int count );
        //конвертирует строки unicode в win1251
        StringBuilder& ToWin1251( const wchar_t* from, int c_from = -1 );

        int Ignore( int p, char c )
        {
            return Str::Ignore( ptr, p, c );
        }
};


Ну это зависит от людей, а не от инструментов. Если человек не хочет учиться, то никакие православные Цэ его не изменят, разница будет лишь в том, что он будет продавать еще более всратую малварь, чем если бы он писал ее на Шарпах или Петухонах. Опять же на Шарпах, зная как работают внутренности фреймворка можно такой забористой бесфайлой малвари написать, что она по многим параметрам будет лучше нативной. Или на Петухонах можно легко написать скриптовый метаморф, используя встроенный модуль ast, а нативного метаморфа стабильного я не видел никогда.


Так и что бы изменилось по твоему? Он бы и на Цэ пытался загрузить 100гб в виртуальную память.
Что скажешь о ISFB? https://github.com/t3rabyt3-zz/Gozi
 
Забавный факт: большинство тех людей, которые топят за ассемблеры/cи/си++ и хейтят другие языки (в целом, я не конкретно о малвари), никогда в своей жизни не писали ничего серьезнее хелловорда. Мы же говорим о разных областях применения, новые технологии создаются для упрощения разработки, никто не будет переплачивать за человекочасы, потраченные на написание большого кода, когда можно заплатить меньше и получить аналогичный результат в более краткий срок. Для каждой задачи свой инструмент.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Что скажешь о ISFB? https://github.com/t3rabyt3-zz/Gozi
Ну как бы выискивать тут баги, утечки памяти, хендлов и тд можно бесконечно, вполне вероятно, что они там есть. Проблема в том, что код достаточно плохо читаем и там нагорожено всего ппц, если и искать проблемы, то какой-то автоматизированной тулзой. В частности, да, это обусловлено отсутствием RAII и нормальных абстракций. Будь у автора возможность не городить вот эти сраные елочки из ифов, а делать поток исполнения линейным с ранними выходами в случае ошибок (а все аллокации и незакрытые хендлы подчищал бы компилятор), то вот этот код, например, был бы куда более читаем:
Код:
static BOOL GenModuleName(
    PULONG        pSeed,    // random seed
    LPTSTR*        pName,    // receives the buffer with the name generated
    PULONG        pLen    // receives the length of the name in chars
    )
{
    BOOL    Ret = FALSE;
    LPTSTR    ModuleName, SystemDir;
    PWIN32_FIND_DATA FindFileData;
    ULONG    NameLen = 0;
    HANDLE    hFind;

    if (FindFileData = (PWIN32_FIND_DATA)hAlloc(sizeof(WIN32_FIND_DATA)))
    {
        if (SystemDir = (LPTSTR)hAlloc(MAX_PATH_BYTES))
        {
            if (ModuleName = (LPTSTR)hAlloc(DOS_NAME_LEN*sizeof(_TCHAR)))
            {
                memset(ModuleName, 0, DOS_NAME_LEN*sizeof(_TCHAR));
                if (NameLen = GetSystemDirectory(SystemDir, (MAX_PATH - cstrlen(szFindDll) - 1)))
                {
                    ULONG i, Steps1, Steps2;
                    HANDLE    hFile;
                    FILETIME MaxFileTime = {ULONG_MAX, ULONG_MAX};

                    // Opening c_1252.nls file and getting it's write time.
                    // Thus we can determine a time when OS was installed.
                    lstrcat(SystemDir, sz1252nls);
                    hFile = CreateFile(SystemDir, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
                    if (hFile != INVALID_HANDLE_VALUE)
                    {
                        GetFileTime(hFile, &MaxFileTime, NULL, NULL);
                        ((PLARGE_INTEGER)&MaxFileTime)->QuadPart += _SECONDS(60*60*24);
                        CloseHandle(hFile);
                    }
                    SystemDir[NameLen] = 0;
                    NameLen = 0;

                    // Initializing rand with machine seed value to generate the same name on the same machine
                    Steps1 = RtlRandom(pSeed) & 0xff;
                    Steps2 = RtlRandom(pSeed) & 0xff;

                    lstrcat(SystemDir, szFindDll);
                    if ((hFind = FindFirstFile(SystemDir, FindFileData)) != INVALID_HANDLE_VALUE)
                    {
                        // Cheking files that were modified earlier then MaxFileTime only
                        while(CompareFileTime(&FindFileData->ftLastWriteTime, &MaxFileTime) > 0)
                        {
                            if (!FindNextFile(hFind, FindFileData))
                            {
                                FindClose(hFind);
                                hFind = FindFirstFile(SystemDir, FindFileData);
                                MaxFileTime.dwHighDateTime = FindFileData->ftLastWriteTime.dwHighDateTime;
                                MaxFileTime.dwLowDateTime = FindFileData->ftLastWriteTime.dwLowDateTime;
                            }
                        }    // while(CompareFileTime(&FindFileData->ftLastWriteTime, &MaxFileTime) > 0)

                        for (i=0; (i<=Steps1 || i<=Steps2); i++)
                        {
                            if (i == Steps1 || i == Steps2)
                            {
                                ULONG nLen = (ULONG)(StrChr((LPTSTR)&FindFileData->cFileName,'.') - (LPTSTR)&FindFileData->cFileName);
                                ULONG nPos = 0;
                                if (NameLen && ((nPos = nLen-4) > nLen))
                                    nPos = 0;
                                if (nLen>4)
                                    nLen = 4;
                                memcpy(ModuleName+NameLen, &FindFileData->cFileName[nPos], nLen*sizeof(_TCHAR));
                                NameLen += nLen;
                            }    // if (i == Steps1 || i == Steps2)

                            do
                            {
                                if (!FindNextFile(hFind, FindFileData))
                                {
                                    FindClose(hFind);
                                    hFind = FindFirstFile(SystemDir, FindFileData);
                                }    // if (!FindNextFile(hFind, FindFileData))
                            } while(CompareFileTime(&FindFileData->ftLastWriteTime, &MaxFileTime) > 0);

                        }    // for (i=0;
                        *pName = ModuleName;
                        *pLen = NameLen;
                        Ret = TRUE;
                        FindClose(hFind);
                    }    // if ((hFind =
                    else
                    {
                        DbgPrint("ISFB: System file not found: \"%s\"\n", SystemDir);
                    }
                }    // if (GetSystemDirectory(

                if (!Ret)
                    hFree(ModuleName);
            }    // if (ModuleName =
            hFree(SystemDir);
        }    // if (SystemDir =
        hFree(FindFileData);
    }    // if (FindFileData =
    
    return(Ret);
}
Это не единственный пример. Опять же, то о чем говорил Шептун: функции конкатенации строк, которые не проверяют выходы за границу буффера. В этом частном случае, может ничего страшного, так как C:\Windows\System32\<имя_длл> уложится в 260 символов, но в общем случае так делать не стоит. Много, где значения возвратов WinAPI функций не проверяются, наверное, это тоже обусловлено сложным потоком выполнения с кучей вложенных ифов (чтобы еще больше ифов не вкладывать). По канонам чистого кода такие длинные или еще длиннее функции писать в принципе нельзя, код должен быть лаконичным и понятным. Раз уж в Цэ есть по сути одна абстракция - процедуры, так вот и разбивал бы код на процедуры, а не делал бы таких портянок, в которых, я уверен, ему самому будет через некоторое время после написания разбираться. Ну и так далее. В общем не сказал бы, что это прям хорошо, работает в большинстве случаев, но никак бы не сказал, что такой код чем-то лучше, чем если бы он был написан на языках с наличием нормальных абстракций.

А во, глядите, толи я уже упорол глаза на это смотреть, толи это действительно баг (читаем комменты помеченные "!!!"):
Код:
VOID _stdcall LoadDllStub(
    PLOADER_CONTEXT    LdrCtx
    )
{
    HANDLE    hModule;
    PCHAR    ImageBase;
    BOOL    Result; // !!! Не инициализирован в FALSE, может быть любое дерьмо со стека (BOOL = int в Цэ вроде как, FALSE - ноль соответственно)

    if (ImageBase = (PCHAR)LdrCtx->ImageBase)
    {
        NTSTATUS        ntStatus = STATUS_SUCCESS;
        FUNC_DLL_MAIN    pDllMain;

        // Initializing DLL image
        PIMAGE_NT_HEADERS Pe = (PIMAGE_NT_HEADERS)(ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew);
        PIMAGE_SECTION_HEADER    Section = IMAGE_FIRST_SECTION(Pe);
        ULONG    i, OldProtect, NumberSections = Pe->FileHeader.NumberOfSections;

        // Resolving module import
        ULONG   ImportStartRVA;
        PCHAR   ModuleName;
        PVOID    ImportedModuleBase = NULL;
        PIAT_ENTRY    pIatEntry = NULL;
        PIMAGE_IMPORT_DESCRIPTOR pImportDesc;

        // Get the import table RVA from the data dir
        if (ImportStartRVA = Pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
        {
            pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(ImageBase + ImportStartRVA);

            // Find the import descriptor containing references to callee's functions
            for (; pImportDesc->Name; pImportDesc++)
            {   
                ULONG NameLen = 0;
                ModuleName = ImageBase + pImportDesc->Name;

                while(ModuleName[NameLen])
                {
                    LdrCtx->wDllPath[NameLen] = (WCHAR)ModuleName[NameLen];
                    NameLen += 1;
                }
                LdrCtx->uDllPath.Length = (USHORT)(NameLen*sizeof(WCHAR));
                LdrCtx->uDllPath.MaximumLength = (USHORT)((NameLen+1)*sizeof(WCHAR));
                LdrCtx->uDllPath.Buffer = (PWSTR)&LdrCtx->wDllPath;
                    
                ntStatus = ((FUNC_LOAD_LIBRARY)LdrCtx->Import.pLdrLoadDll)(NULL, 0, &LdrCtx->uDllPath, &ImportedModuleBase);
                if (NT_SUCCESS(ntStatus))
                {
                    ULONG   rvaINT = pImportDesc->OriginalFirstThunk;
                    ULONG   rvaIAT = pImportDesc->FirstThunk;
                    PIAT_ENTRY    pIatEntry = NULL;
                    PIMAGE_IMPORT_BY_NAME   pOrdinalName;
                    PIMAGE_THUNK_DATA        pINT;
                    PIMAGE_THUNK_DATA        pIAT;
                    IAT_ENTRY                IatEntry;
                    USHORT                    Ordinal = 0;

                    if ( rvaINT == 0 )   // No Characteristics field?
                        rvaINT = rvaIAT;
        
                    if ( rvaINT != 0 )   // No FirstThunk field?  Ooops!!!
                    {
                        // Adjust the pointer to point where the tables are in the mem mapped file.
                        pINT = (PIMAGE_THUNK_DATA)(ImageBase + rvaINT);
                        pIAT = (PIMAGE_THUNK_DATA)(ImageBase + rvaIAT);

                        while (TRUE) // Loop forever (or until we break out)
                        {   
                            if (pINT->u1.AddressOfData == 0)
                                break;

                            if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal) == FALSE)
                                pOrdinalName = (PIMAGE_IMPORT_BY_NAME)(ImageBase + (ULONG)pINT->u1.AddressOfData);
                            else if (pINT->u1.Ordinal >= (ULONG_PTR)ImageBase && pINT->u1.Ordinal < ((ULONG_PTR)ImageBase + Pe->OptionalHeader.SizeOfImage))
                                pOrdinalName = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)pINT->u1.AddressOfData);
                            else
                            {
                                pOrdinalName = NULL;
                                Ordinal = (USHORT)IMAGE_ORDINAL(pINT->u1.Ordinal);
                            }
                                
                            if (pOrdinalName)
                            {
                                NameLen = 0;
                                while(pOrdinalName->Name[NameLen])
                                    NameLen += 1;

                                LdrCtx->uDllPath.Length = (USHORT)NameLen;
                                LdrCtx->uDllPath.MaximumLength = (USHORT)(NameLen + 1);
                                LdrCtx->uDllPath.Buffer = (PWSTR)&pOrdinalName->Name;
                                pOrdinalName = (PIMAGE_IMPORT_BY_NAME)&LdrCtx->uDllPath;
                            }

                            ntStatus = ((FUNC_PROC_ADDRESS)LdrCtx->Import.pLdrGetProcedureAddress)(ImportedModuleBase, (PANSI_STRING)pOrdinalName, Ordinal, (PVOID*)&IatEntry);
                            if (NT_SUCCESS(ntStatus))
                            {
                                pIatEntry = &pIAT->u1.Function;
                                *pIatEntry = IatEntry;
                            }
                            else
                            {
                                ntStatus = STATUS_PROCEDURE_NOT_FOUND;
                                break;
                            }

                            pINT++;         // advance to next thunk
                            pIAT++;         // advance to next thunk
                        } // while (TRUE)   
                    }    // if ( rvaINT != 0 )
                }    // if (NT_SUCCESS(ntStatus))
                else
                {
                    ntStatus = STATUS_INVALID_IMPORT_OF_NON_DLL;
                    break;
                }
            } // for (; pImportDesc->Name; pImportDesc++)
        }    // if (ImportStartRVA = Pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)


        if (NT_SUCCESS(ntStatus))
        {
            ULONG_PTR    tSize = (ULONG_PTR)Pe->OptionalHeader.SizeOfHeaders;
            // Restoring sections' protection
            ntStatus = ((FUNC_PROTECT_MEM)LdrCtx->Import.pNtProtectVirtualMemory)((HANDLE)-1, (PVOID*)&ImageBase, &tSize, PAGE_READWRITE, &OldProtect);
            for (i=0; (i<NumberSections && NT_SUCCESS(ntStatus)); i++)
            {
                ULONG    NewProtect = 0;
                PVOID    BaseAddress;
    
                if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
                {
                    if (Section->Characteristics & IMAGE_SCN_MEM_WRITE)
                        NewProtect = PAGE_EXECUTE_READWRITE;
                    else
                        NewProtect = PAGE_EXECUTE_READ;
                }
                else if (Section->Characteristics & IMAGE_SCN_MEM_READ)
                {
                    if (Section->Characteristics & IMAGE_SCN_MEM_WRITE)
                        NewProtect = PAGE_READWRITE;
                    else
                        NewProtect = PAGE_READONLY;
                }
                else
                    NewProtect = PAGE_READWRITE;

                tSize = (ULONG_PTR)Section->Misc.VirtualSize;
                BaseAddress = (PVOID)(ImageBase + Section->VirtualAddress);
                ntStatus = ((FUNC_PROTECT_MEM)LdrCtx->Import.pNtProtectVirtualMemory)(NtCurrentProcess(), &BaseAddress, &tSize, NewProtect, &OldProtect);
                Section += 1;
            }    // for (i=0; i<NumberSections; i++)
        
            if (NT_SUCCESS(ntStatus))
            {
                // Calling DLL entry point
                pDllMain = (FUNC_DLL_MAIN)(ImageBase + Pe->OptionalHeader.AddressOfEntryPoint);
                Result = (pDllMain)(ImageBase, DLL_PROCESS_ATTACH, &LdrCtx->AdContext); // Устанавливает значение тут
            }    // if (NT_SUCCESS(ntStatus))
        }    // if (NT_SUCCESS(ntStatus))
    }    // if (ImageBase = LdrCtx->ImageBase)
    else
    {
        // Loading DLL by name
        if (NT_SUCCESS(((FUNC_LOAD_LIBRARY)LdrCtx->Import.pLdrLoadDll)(NULL, 0, &LdrCtx->uDllPath, &hModule)))
            Result = TRUE; // !!! Устанавливает значение тут
    }

#ifdef    _BK_CALL_EXPORT
    
    // !!!
    // Значение Result меняется только в случае удачной загрузки PE-файла
    // В случае неудачной загрузки сюда придет неинициализированное значение Result
    // Которое с наибольшей вероятность не FALSE, поэтому код создаст поток хер пойми на куда
    // !!!

    if (Result && LdrCtx->ExportedFunction)
    {
        ULONG pThreadId;
        ((FUNC_CREATE_THREAD)LdrCtx->Import.pCreateThread)(NULL, 0, &LdrCtx->ExportStub, LdrCtx, 0, &pThreadId);
    }
#endif
}
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так а чего там Цэшного,
Перепутал значит, в архиве см. другой проект.

Так и что бы изменилось по твоему? Он бы и на Цэ пытался загрузить 100гб в виртуальную память.

Как минимум, нелогично было бы писать malloc(1024*1024*1024*100) , хотя хрен их знает, этих людей; но в любом случае, он бы хоть понимал, что оно работает не магией.

Для каждой задачи свой инструмент.
Так я согласен полностью, и сам использую PHP, Perl для текста VB/RAD студио для гуев. Но для малвари нужно использовать низкоуровневые языки.
 
Перепутал значит, в архиве см. другой проект.



Как минимум, нелогично было бы писать malloc(1024*1024*1024*100) , хотя хрен их знает, этих людей; но в любом случае, он бы хоть понимал, что оно работает не магией.


Так я согласен полностью, и сам использую PHP, Perl для текста VB/RAD студио для гуев. Но для малвари нужно использовать низкоуровневые языки.
Не всегда и не везде. Я занимаюсь пентестом и часто пишу софт для себя сам, не прибегая к услугам сторонних исполнителей. Какой нибудь стиллер будет проще накодить на шарпе/расте, зачем усложнять себе жизнь? Из под высокоуровневых яп не особо приятно работать с низкоуровневыми вещами, но это и не нужно в контексте данной задачи. Если я одинаково хорошо владею несколькими яп, проще взять подходящий и не тратить лишнее время на реализацию базовых вещей. Ты смотришь на такие вещи с точки зрения коммерции и школьников, которые пишут на шарпе/голанге/питоне просто потому, что не могут на чём то другом.)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Но для малвари нужно использовать низкоуровневые языки
Почему же? Цэ не дает существенных преимуществ в сравнении с Плюсами или Нимом или Дэ или Растом. Как бы все те же самые возможности, но с поддержкой абстракций. Даже на православном чистом WinAPI можешь писать, переизобретая все нужные тебе абстракции, если желаешь. Я бы даже сказал, для любой малвари, кроме шкафчиков, сейчас вполне подходят и Шарпы.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Цэ не дает существенных преимуществ в сравнении с Плюсами или Нимом или Дэ или Растом.
Не могу сказать за дэ или раст, но так то у Си нулевой рантайм. В плане, можно легко обойтись без стандартной либы. по иному - мб и правда дело привычки, хз.

Ты смотришь на такие вещи с точки зрения коммерции и школьников, которые пишут на шарпе/голанге/питоне просто потому, что не могут на чём то другом.)
Да, ты полностью прав. Если для тебя шарп это инструмент , то для меня - это очередной школьник, который выучился копипастить, и пытается обмануть народ очередным убер-приватом.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Не могу сказать за дэ или раст, но так то у Си нулевой рантайм
Так то и у Дэ, и у Нима, и у Раста, и у Ады, и у Паскаля, и у Басиков разных есть возможность отключение рантайма. В этом плане даже Шарпы можно докрутить до без рантаймов, если сделать годный нативный компилятор, что когда-то доказали проекты менеджд операционных систем, такие как Mosa, Cosmos или Singularity.
 
Оч интересный тред и особенно познавательный будет для новичка малварь-кодера, если он дочитает до сюда, но все равно 9 из 10 людей поймет посыл треда неправильно. Человек, который не имеет опыта коммерческой разработки чего-то большого сидит и спорит со всеми остальными, что любой кодер знать обязан WinAPI, ASM, FASM, все возможные Assembly, а до кучи Теория информация, вычислительную математику, архитектуру ЭВМ. В реальности же, тут верно сказали. Для каждой задачи есть свой инструмент и даже для определенной задачи есть разные подходы/разные решения. Как уже сказали, если разработка малвари, которая приносит итоговый профит на Rust/Python стоит гораздо дешевле материальных и нематериальных ресурсов при соразмерном выхлопе, то какой смысл делать ее на С?
Всю дорогу в ВУЗе разработку на С боготворили только те, кто ничему другому больше не научился, закостенел и пытается, просто, хоть как-то оправдать потраченное время. Абсолютно точно, если речь идет о контрибьюте в публичные репо PostgreSQL, условно, то без С там делать нечего, но ни одного из таких высокоуровневых кодеров с пониманием реляционной алгебры нет в комментариях. У таких людей просто нет запроса доказывать что питонисты -- говно, а они 10 лет учились, кровью и потом навык поднимали.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
то какой смысл делать ее на С?
Никакого. У меня просто стокгольмский синдром. Так то можно кодить на новых языках типа раст, дотнет и прочие питоны. Си не нужен.
Больше в подобных темах участвовать не буду, можете скринить.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Никакого. У меня просто стокгольмский синдром. Так то можно кодить на новых языках типа раст, дотнет и прочие питоны. Си не нужен.
Больше в подобных темах участвовать не буду, можете скринить.
Если бы это не сарказм был...
Зато ты можешь себя успокаивать тем что можешь на С заработать больше чем 99.9% кодеров в мире, написанием хорошей малвари.
 
И все таки возвращаясь к Столярову, уважаемые знатоки, подскажите. У него выстроена логика в изучении: паскаль-ассемблер-Си. Натыкался на мнение, вроде на Хабре, не помню точно, что после Паскаля тяжело переходить на Си. При этом здесь в топике звучали тезисы от тех кто проходил путь Ассемблер-Си, конкретно в этом порядке, сравнивали это по описанию с чем-то напоминающим каторгу, притом что особо никто не спорит и с тем что и с Си начинать непросто.

Так вот вопрос, стоит ли идти в таком порядке или лучше сразу начинать с Си и не тратить время?

Я понимаю, почему автор предлагает пробежаться по Паскалю, так как книга рассчитана на разных людей и кто-то воообще никогда не сталкивался с ЯП, но я лично какое-то количество лет назад сталкивался прямо по верхам с бейсиком и Паскалем, не уверен правда что достаточно глубоко и поэтому присутствует страх что-то важное пропустить из основ, срезав маршрут. И интересует что рациональнее, вначале Ассемблер с горем по верхам и потом уже учить Си и развиваться дальше, или в обратном порядке, в какой-то момент вернувшись к Ассемблеру? Рациональнее мне кажется первый вариант, но тогда это повторение тяжелого пути Quake)) Kumarin, твое мнение как чеовека несколько опережающего меня на этой дороге, тоже интересно выслушать!
P.S. Согласен с озвученным здесь мнением, что начав учить более простые в освоении языки скорее всего навсегда закрою себе дорогу к более сложным.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Сейчас имеет очень мало смысла учить Паскаль, на практике он мало, где используется, и вряд ли когда-то в будущем тебе пригодиться. Если ты не знаешь ни одного языка и не программировал вовсе до этого, то начинай с Петона, изучай на нем основные концепции, алгоритмы и тд, получи опыт. Если знаешь хотя бы один язык и имеешь опыт программирования на нем, то нет существенной разницы, что после чего учить. Интересен язык - учи. Всякие пути обучения, которые рекомендовались 10-20 лет назад, не то чтобы так прям актуальны сейчас.
 
тезисы от тех кто проходил путь Ассемблер-Си, конкретно в этом порядке, сравнивали это по описанию с чем-то напоминающим каторгу
они не шарят
учи ассемблер это база и основа всего
 
не программировал вовсе до этого, то начинай с Петона
Я насколько понимаю это даст понимание об общей логике в программировании, что весьма облегчит путь в дальнейшем, но не будет ли пагубных последствий в будущем? Я так понимаю, язык Си учит более структурировано и канонично подходить к написанию кода, ошибаюсь?
Про Паскаль подтвердили мои догадки, благодарю

они не шарят
ну Quake3 создает образ компетентного спеца) Думаю вы просто не так поняли мой вопрос
Я определенно согласен, что знание и понимание ассемблера необходимо хорошему специалисту и это вроде никто не поддавал сомнению, тут скорее вопрос в последовательности в изучении, так как ассемблер, со слов, весьма сложен для понимания малоподготовленного человека
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх