издевался тут над макросами хотел сделать поудобней общение с глобальными переменными в базонезависимом коде на wasm.ru взял идею получилось так сперва объявляем макпрос VX_SEQ такого содержания Code: #define VX_SEQ (n1)(n2)(n3)(n4)(n5)(n6)(n7)(n8)(n9) каждый элемент в последовательности это имя переменной переменные будем хранить в коде функции второй строчкой подключаем заголовочный файл поддержки Code: #include "vx_var.h" следом определяем функцию get_delta следом __variables__ в ней будем хранить переменные выглядит это так Code: __declspec(naked) DWORD get_delta() { __asm { call __1 __1: pop eax sub eax, offset __1 ret } } __declspec(naked) void __variables__() { VX_DECLARE_VAR; } VX_DECLARE_VAR это иакрос в зависимости от кол элементов в VX_SEQ генерирует нужное кол-во __emit 0xcc все переменные расширяются до 4 байт можно хранить float но по указателю иначе при кастинге потеряем дробную часть все в коде чтоб считать установить переменную пишем Code: int var = VX_READ(n1); это читает переменную n1 Code: VX_WRITE(n1,0xdeadc0de); это пишет перменную n1 если указать неверное имя компилятор отловит главное создать файл @order.txt в нем перечислить функции в нужном порядке чтобы потом размер кода всех функций вычислить реализация простая модифицируем каждый элемент последовательности в тип и создаем loki_typelist потом когда нам передают имя в vx_read или vx_write мы это имя переводим в тип и ищем индекс этого типа в списке дальше проверяем что идекс не -1 это если несуществующее имя указать и дальще читаем вот как это выглядит Code: template<int n> struct vx_check { typedef char dup[n!=-1?1:-1]; enum{_n=n}; }; #define VX_SEQ_TRANSFORM(s,data,elem) struct elem * #define VX_SEQ_N(name) (Loki::TL::IndexOf<BOOST_PP_CAT(BOOST_PP_EXPAND(BOOST_PP_CAT(LOKI_TYPELIST_,BOOST_PP_SEQ_SIZE(VX_SEQ))),BOOST_PP_EXPAND((BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(VX_SEQ_TRANSFORM,~,VX_SEQ))))),struct name*>::value) #define VX_READ(n) (PDWORD((DWORD(&__variables__)+get_delta()))[vx_check<VX_SEQ_N(n)>::_n]) #define VX_WRITE(n,v) (PDWORD((DWORD(&__variables__)+get_delta()))[vx_check<VX_SEQ_N(n)>::_n]=v) вот код который забивает функцию __variables__ переменными просто в цикле делает __emit 0xcc Code: #define VX_EMIT_CC(z,n,data) __asm{__emit 0xCC} #define VX_EMIT_CC_X4(z,n,data) BOOST_PP_REPEAT(4,VX_EMIT_CC,~) #define VX_DECLARE_VAR BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(VX_SEQ),VX_EMIT_CC_X4,~) приведу полный пример Code: #define VX_SEQ (n1)(n2)(n3)(n4)(n5)(n6)(n7)(n8)(n9) #include "vx_var.h" #pragma optimize("gpsty", off) G_BEGIN_DECLS // extern "C" { __declspec(naked) DWORD get_delta() { __asm { call __1 __1: pop eax sub eax, offset __1 ret } } __declspec(naked) void __variables__() { VX_DECLARE_VAR; } void entry() { int njks = VX_READ(n9); VX_WRITE(n9, 0x999); char cv = 'j'; short sv = 78; int dw = 7; VX_WRITE(n9,dw); VX_WRITE(n9, cv); VX_WRITE(n6, sv); njks = VX_READ(n1); njks = VX_READ(n9); } void end_code_seg_() {} G_END_DECLS // } #pragma optimize("", on) int main() { size_t size = intptr_t(&end_code_seg_) - intptr_t(&entry); void *exec = malloc(size); memcpy(exec, entry, size); ((void(*)())exec)(); } содержимое order.txt Code: entry get_delta __variables__ end_code_seg_ в исходнике между #pragma optimize их можно расположить как удобно но чтоб правильно вычислить размер entry надо прописать первой а end_code_seg_ последней содержимое vx_var.h Code: #ifndef __VX_VAR__ #define __VX_VAR__ #ifndef LOKI_TYPELIST_INC_ #include <loki/typelist.h> #endif #ifndef BOOST_PREPROCESSOR_CAT_HPP #include <boost/preprocessor/cat.hpp> #endif #ifndef BOOST_PREPROCESSOR_FACILITIES_EXPAND_HPP #include <boost/preprocessor/facilities/expand.hpp> #endif #ifndef BOOST_PREPROCESSOR_SEQ_SIZE_HPP #include <boost/preprocessor/seq/size.hpp> #endif #ifndef BOOST_PREPROCESSOR_SEQ_ENUM_HPP #include <boost/preprocessor/seq/enum.hpp> #endif #ifndef BOOST_PREPROCESSOR_SEQ_TRANSFORM_HPP #include <boost/preprocessor/seq/transform.hpp> #endif #ifndef BOOST_PREPROCESSOR_REPETITION_REPEAT_HPP #include <boost/preprocessor/repetition/repeat.hpp> #endif template<int n> struct vx_check { typedef char dup[n!=-1?1:-1]; enum{_n=n}; }; #define VX_SEQ_TRANSFORM(s,data,elem) struct elem * #define VX_SEQ_N(name) (Loki::TL::IndexOf<BOOST_PP_CAT(BOOST_PP_EXPAND(BOOST_PP_CAT(LOKI_TYPELIST_,BOOST_PP_SEQ_SIZE(VX_SEQ))),BOOST_PP_EXPAND((BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(VX_SEQ_TRANSFORM,~,VX_SEQ))))),struct name*>::value) #define VX_READ(n) (PDWORD((DWORD(&__variables__)+get_delta()))[vx_check<VX_SEQ_N(n)>::_n]) #define VX_WRITE(n,v) (PDWORD((DWORD(&__variables__)+get_delta()))[vx_check<VX_SEQ_N(n)>::_n]=v) #define VX_EMIT_CC(z,n,data) __asm{__emit 0xCC} #define VX_EMIT_CC_X4(z,n,data) BOOST_PP_REPEAT(4,VX_EMIT_CC,~) #define VX_DECLARE_VAR BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(VX_SEQ),VX_EMIT_CC_X4,~) #endif /* __VX_VAR__ */ писано ради интереса во время написания одной утилитки
чтоб иметь "глобальные переменные" адресация к глобальным переменным в чужом процессе не как обычно по абсолютным адресам надо добавлять дельту или зачем это нужно ? я писал утилитку она слала мне данные через WM_COPYDATA WriteProcessMemory(last_proc-first_proc) CreateRemoteThread например два потока часто делят некие глобальные переменные там то это и пригодится