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

Курс по С++ с уклоном в тематику форума

Нужен ли курс по С++, с уклоном в тематику форума?


  • Можно выбрать несколько вариантов.
Когда кто-то говорит о том что бы что-то следать на чистом си, он признается что очень серьезно отстал в развитии. Вообще когда видишь сочитание слов "чистый си" это повод держаться от чувака подальше =)
"C-style C++ is All You Need."

Не бро, ты не выкупаешь, они же говорят не си, а _ЧИСТЫЙ СИ_ и это типа очень круто и элитно =), они достигли, они гордятся.
jj2bn.jpg

It’s a pity that after 50+ years of progress, we still love doing the compiler’s job.
The same shit with vim/emacs.
I use nvim btw.)

I hate most abstractions that come with C++, but I need C++ for the ones I don't want to break my brain over with C or worse: shooting myself in the foot.

If you are working on something like a game engine, there's a no brainer here.
Kernel dev, embedded systems sticking with C is understandable.

Употребляя выражение "чистый си" - я даю понять, что используется только низкоуровневый апи
s.png


его проще морфить
Why the hell are you even working at the front end level (source code or AST)? Not funny. Try something rudimentary as control flow flattening at the clang AST level vs LLVM IR level and let me know which one kills your libido.)
Do yourself a favor and study LLVM IR. It's SSA. Fuck trees, libclang. There's a reason Chris Lattner worked so hard so that one day we could all unite under one umbrella.
And no need to go against the grain with GCC GIMPLE.

Слушай, если ты тоже будешь регулярно подмывать свой си, он и у тебя будет чистый, в этом нет ничего такого. Я бы, наверное, говорил "на чистом винапи", или на "чистом нтапи"
There's something in every syscoder's primal instincts that raise our dopamine levels every time someone says "pure C". None can escape this instinct. Not even Whisper

С термином все ок, он про синтаксис языка и означает что кодер не будет использовать си с классами.
И все это означает что кодер напишет код который не будет гибким, не будет нормально тестироваться или это будет лютый пиздец с инъекцией зависимости на чистом си, что само по себе будет говорить о том что кодер очень странный парень.
Короче упоминать про си и особенно про чистый си да еще и преподносить это как что то хорошее это как заявлять о собственной тупизне и необучаемости. Завязывай с си.
It's already pretty obvious that he either works at the source code or AST level or worse (most likely): believes that C binaries somehow make obfuscation easier.

Главное в курсе о С/С++ не забыть рассказать о новом API для выделения памяти, которое скоро станет стандартным:
Посмотреть вложение 97789
C:
int* x = (int*)mallocPlusAI("Enough memory to store up to 5 ints");
freePlusAI(x, "I think it’s time...");
 
Why the hell are you even working at the front end level (source code or AST)? Not funny. Try something rudimentary as control flow flattening at the clang AST level vs LLVM IR level and let me know which one kills your libido.)
Do yourself a favor and study LLVM IR. It's SSA. Fuck trees, libclang. There's a reason Chris Lattner worked so hard so that one day we could all unite under one umbrella.
And no need to go against the grain with GCC GIMPLE.
Я работал с ллвм ир, мощный инструмент, но достаточно сложный в освоении

Обфусцируя код на уровне ир кода - нужно генерировать правдоподобный код, который выглядел бы так, как генерирует компилятор

Морфя код на уровне сорсов не нужно так сильно беспокоиться по поводу этого, ведь генерация байт кода выполняет сам компилятор
There's something in every syscoder's primal instincts that raise our dopamine levels every time someone says "pure C". None can escape this instinct. Not even Whisper
:)
 
Я работал с ллвм ир, мощный инструмент, но достаточно сложный в освоении

Обфусцируя код на уровне ир кода - нужно генерировать правдоподобный код, который выглядел бы так, как генерирует компилятор
Не сказать что сложный - хороший лангреф, высокоуровневые штуки достаточно просто генерировать - пишем на Си какую-либо конструкцию -> компилируем в LLVM IR и анализируем вывод. Гораздо больше трудностей работать с IR програмно на ЯП, отличном от С++, т.к сишные бинды сильно лимитированы - проблема решаема, но иного выхода как парсить IR вручную в свою in memory модель я не нашёл.
 
Не сказать что сложный - хороший лангреф, высокоуровневые штуки достаточно просто генерировать - пишем на Си какую-либо конструкцию -> компилируем в LLVM IR и анализируем вывод. Гораздо больше трудностей работать с IR програмно на ЯП, отличном от С++, т.к сишные бинды сильно лимитированы - проблема решаема, но иного выхода как парсить IR вручную в свою in memory модель я не нашёл.
I remember when llvmlite first emerged, I was happy at the thought of py3 bindings. Not that I would ever use lower my standards to any sort of bindings (joke) (but also true) but was somewhat happy about a newfound accessibility for noobs. C++ API is the definitive way. The C-API is a pain in the ass with an incomplete coverage. An obvious reason is that the whole LLVM C++ API pipeline is designed to be OOPs heavy. Compare the most basic needs: llvm::Module, Function, BasicBlock. Extremely awkward to work with in C with raw func calls to fuck with pointers. Opaque pointers (eg LLVMModuleRef, LLVMValueRef)
templates llvm::SmallVector<T> llvm::DenseMap<K, V> Expected<T> llvm::ArrayRef<T>
generic visitors InstVisitor
llvm::DiagnosticInfo llvm::Error are godsends
and there are problems with coverage as well: example metadata

now my experiments with llvmlite, first off, it only caters to numba's needs and even with that extremely small subset, there's a shit ton of bugs (i once tried to write my own custom backtracking utility because the stupid thing didn't have it and Im sure still doesnt, this makes everything unusable, the codebase is extremely fragile and the one thing that's perfectly obvious is that the authors initially (maybe to this date) never intended to make it cover the whole C++ API) and important features missing: solid instruction, op tracking, types, backtracking etc.

If there is a demand for this specific type of shit on the forum, i am willing to follow Snow with the next article.) If someone's down to collaborate (article writing is painful) or suggest any specific ideas: write a new sillly kind of control flow flattening, something unique than the boring old, abused OG OLLVM flattening. Like maybe a weird dispatch mechanism or whatever you dream of.

Please, write down ideas for the tasks, ideally something that's not implemented publicly or a mild to moderate (maybe even extreme, why not?) variant of a public implementation.

I didn't have much experience with GIMPLE but if someone's interested, we could go hand in hand with the same Pass. Though I don't see any compelling reason.

I want to showboat my LLVM (mid end + back end) expertise contribute, have fun.

PS. I take punctuation seriously but this one was in a hurry.

but I have not found any other way out than to parse IR manually into my in memory model.
This is what I was talking about with the custom backtracking utility for llvmlite. Now forget llvmlite.
Take this noobish instruction: %1 = add i32 %a, %b
You have to recognize %1 as a new SSA variable, Parse the operation (add), types (i32), and operands (%a, %b).
Parser for well defined SSA is easy for the parsing parts but there's much more that needs to be done if you want to make actually make any use of it.
Backtracking is the most rudimentary one that llvmlite sucks at. Forget codegen for a while.
And there are phi nodes
%result = phi i32 [ %a, %then ], [ %b, %else ]
you have to parse the types and SSA variables in both branches (%a, %then, %b, %else).
You need to maintain a mapping of which variables are valid in each BB and understand how values flow based on control flow. (SSA tracking)
If an article is written, this is a crucial example that needs to be demonstrated practically. I am adding a marker.

There are boat load of clauses, align, atomic, nounwind, readonly

Look at the language manual https://llvm.org/docs/LangRef.html#alloca-instruction
<result> = alloca [inalloca] <type> [, <ty> <NumElements>] [, align <alignment>] [, addrspace(<num>)] ; yields type addrspace(num)*:result
and all sorts of caveats and footnotes

There's nothing easier, perfect than the C++ API. I advise anyone new to this to get a lay of the land with the paradigm of modules, LLVMContext, PassManager, IRReader etc before diving into obfuscation optimizations
 
By obfuscating code at the ir code level, you need to generate plausible code that would look like what the compiler generates
"Genuine" programs can't have complex binaries, in terms of data manipulation, control flow?
But yes, the essence of your statement within the theme of the forum is conveyed.
because the compiler itself performs the generation of byte code
byte code for the CPU? yes lol.
bytecode isn't the right term here, you could simply just say binaries
What's a compiler for? For those that can't communicate large/complex logic directly with the CPU properly.
Morphing code at the source level, you don’t need to worry so much about this, because the compiler itself performs the generation of byte code
Abstraction level matters. The same optimization pass at the LLVM IR level is extremely convenient (thank SSA nature + LLVM API). Now it gets difficult with trees (AST), and finally with C/C++ abstractions + syntax, find them pretty?
The abstraction doesn't simplify much with AST generation.
 
This is what I was talking about with the custom backtracking utility for llvmlite. Now forget llvmlite.
Take this noobish instruction: %1 = add i32 %a, %b
You have to recognize %1 as a new SSA variable, Parse the operation (add), types (i32), and operands (%a, %b).
Parser for well defined SSA is easy for the parsing parts but there's much more that needs to be done if you want to make actually make any use of it.
И в чём проблема? Регистры %a и %b мы уже спарсили выше, присвоили им какие-то ID, сохранили в контексте - у нас есть всё необходимое чтоб получить их значение, для этого нам достаточно обратится к контексту по ValueID. Для парсинга инструкции add нам достаточно записать в тот же контекст данные вида: Operand::Add {/*nuw, nsw, */ ty, args: [a_value_id, b_value_id] } с каким-либо уникальным айди. По итогу мы имеем удобную для работы связанную структуру модуля без использования LLVM: знаем все контстантые данные, их типы, можем с лёгкостью найти всех пользователей любого значения.
 
Я имел ввиду какая будет цена курса , но уже на предыдущих страницах увидел что вроде бесплатно.
but there's much more that needs to be done if you want to make actually make any use of it.
Phi nods can be parsed like any other instr, but handling them correctly is non-trivial. For example, if %a and %b are assigned in different branches, their values need to be merged correctly at join points using phi nodes, which isn't just about retrieving IDs from the context. You need to carefully track which values dominate specific BBs + ensure SSA remains valid.
def-use chains + backtracking through the context is not trivial in practice. Of course, we love SSA for its ease with such analysis but as IR grows maintaining these chains efficiently is not easy. If you are eliminating dead code, just knowing the IDs isn't enough, you need to track every use of a var across the entire module. llvm::Value handles it beautifully.

PS. lot of times, a special handling is necessary at the end or throughout for these miscreants
 
On top of this, the simpleton SSA starts to break down when you start dealing with mutable state, especially memory. For example, with 'atomic' ops / pointer aliasing, you can’t just treat variables like simple values. A simple ID storage doesn't account for this.
 
And one more thing: I am talking as if SSA parsing and context setting itself is a monumental task. Of course not.)
That's ridiculous. And now that I look back at my messages, the tone might've been that way, so, sorry. Of course not. Lol. LLVM has "real shit" to take care of.
 
Не сказать что сложный - хороший лангреф, высокоуровневые штуки достаточно просто генерировать - пишем на Си какую-либо конструкцию -> компилируем в LLVM IR и анализируем вывод. Гораздо больше трудностей работать с IR програмно на ЯП, отличном от С++, т.к сишные бинды сильно лимитированы - проблема решаема, но иного выхода как парсить IR вручную в свою in memory модель я не нашёл.
Не совсем понял, что такое фи ноды
И как под виндой адекватно писать пасы? при каждом изменении паса нужно пересобирать проект
Под линуксом вроде можно отдельными либами скармливать прямо в командной строке
 
Не совсем понял, что такое фи ноды
И как под виндой адекватно писать пасы? при каждом изменении паса нужно пересобирать проект
Под линуксом вроде можно отдельными либами скармливать прямо в командной строке
Я писал небольшую модификацию для OLLVM, что бы регулировать обфускацию некоторых функций, и еще что то, что уже не вспомню
И процесс меня весьма утомил, при том, что большее количество времени я потратил на сборку пересборку
 
I didn't have much experience with GIMPLE but if someone's interested, we could go hand in hand with the same Pass. Though I don't see any compelling reason.
Как любитель компиляторов GNU - я первым делом пошел читать про GIMPLE, но нашел я очень не многое

В случае с LLVM - мне удалось найти побольше информации, но все же многое изучалось путем анализа исходного кода)
 
I want to showboat my LLVM (mid end + back end) expertise contribute, have fun.


Было бы интересно почитать статьи про LLVM от тебя

Нет нужды описывать как устроен IR код, на ютубе есть понятные видео на эту тему

Хотелось бы поподробнее узнать про написание проходов

В частности - взаимодействие с нодами, какие они бывают

Ну и как эффективно это делать, я выше писал о своей проблеме - долгой сборкой проекта после изменения в пасе
 
"Genuine" programs can't have complex binaries, in terms of data manipulation, control flow?
But yes, the essence of your statement within the theme of the forum is conveyed.
У компиляторов есть свои особенности кодогенерации

Приведу самый простой:

GCC при вызове функции не использует push инструкцию, он использует mov

Код:
mov    eax, DWORD PTR _ntdll
mov    DWORD PTR [esp+4], 116409954
mov    DWORD PTR [esp], eax
call    _GetProcAddressI

MSVC - не могу сказать точно, но помоему там используется push
 
Abstraction level matters. The same optimization pass at the LLVM IR level is extremely convenient (thank SSA nature + LLVM API). Now it gets difficult with trees (AST), and finally with C/C++ abstractions + syntax, find them pretty?
The abstraction doesn't simplify much with AST generation.
Морфить плюсы на уровне AST - занятие не из простых

Но я уже имею хороший опыт морфинга Си, и не вижу больших проблем в этом
 
And how to adequately write passes under Windows? Every time you change the pass, you need to rebuild the project
Under Linux, it seems that you can feed them with separate libs directly on the command line
I wrote a small modification for OLLVM to regulate the obfuscation of some functions, and something else that I don’t remember anymore
And the process really tired me, despite the fact that I spent more time on assembling and reassembling
Building the entire compiler? lol, just kidding.
If you have a cmake or whatever, I can help.
For starters, ditch llvm-config --libs all
У компиляторов есть свои особенности кодогенерации

Приведу самый простой:

GCC при вызове функции не использует push инструкцию, он использует mov

Код:
mov    eax, DWORD PTR _ntdll
mov    DWORD PTR [esp+4], 116409954
mov    DWORD PTR [esp], eax
call    _GetProcAddressI

MSVC - не могу сказать точно, но помоему там используется push
So, what's your point?
 
looks like a cheap advertisement for his services
dvxmode
21asdj.jpg


PS. "The devil can cite Scripture for his purpose. An evil soul producing holy witness Is like a villain with a smiling cheek, A goodly apple rotten at the heart. Oh, what a goodly outside falsehood hath!" - William Shakespeare
 
Последнее редактирование:


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