1. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    издевался тут над макросами хотел сделать поудобней общение
    с глобальными переменными в базонезависимом коде на 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__ */
    
    писано ради интереса во время написания одной утилитки
     
    2 people like this.
  2. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Можно в двух словах зачем это?
     
  3. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    чтоб иметь "глобальные переменные"
    адресация к глобальным переменным в чужом процессе не как обычно
    по абсолютным адресам надо добавлять дельту
    или зачем это нужно ?
    я писал утилитку она слала мне данные через WM_COPYDATA
    WriteProcessMemory(last_proc-first_proc)
    CreateRemoteThread
    например два потока часто делят некие глобальные переменные
    там то это и пригодится