Inline hook-dolaczanie kodu i przekazywanie parametrow

0

Witam ponownie, we wcześniejszym wątku pomógł mi MSM za co bardzo Ci dziękuje, ale mam jeszcze 2 sprawy do obgadania. Chciałbym zrobić 2 rzeczy:

1)Jeżeli funkcja X się wykona, dodaję na jej koniec własny kod. Tak aby funkcja X wykonywała bez problemu swój kod, ale żeby także na końcu wywołała moje instrukcje. Ogólnie mowiąc - powiększenie funkcji X.

Przykład.

void MojaFunkcja(void)
{
     cout << "Pies pogryzł Ali kota";
}

void FunkcjaX(void)
{
       cout << "Ala ma kota" << endl;
       cout << "Ciesze sie z tego bardzo!" << endl;
       MojaFunkcja(); //Wykonanie metodą inline hook
}

To wszystko oczywiście miałoby się odbywać metodą inline hook.

  1. Drugą sprawą jest to, żeby założyć inline hook'a na funkcję X i w czasie jej wywołania przez program przekierowywała parametry (argumenty) do mojej funkcji. Funkcja X ma bezproblemowo wykonywać swój kod, tylko po prostu te wartości argumentów, które zostały do niej użyte zostały przekierowane do mojej.

Przyklad:


void MojaFunkcja(int inter, char *ch)
{
      cout << "Wartosci parametrow Funkcji X to:" << endl;
      cout << "INT: " << inter << endl;
      cout << "CHAR*: " << ch << endl;
}

void FunkcjaX(int inter, char *ch)
{
       run(inter); //Jakas tam przykladowa operacja
       run2(ch); //Jakas tam przykladowa operacja
}

Bede niezmiernie wdzięczny za pomoc.

0

Ave!
Postaram się odpowiedzieć na obydwa pytania na raz. Niestety teraz będzie trochę trudniej, bo wstawka assemblerowa jest niezbędna.

Kod:

#include <iostream>
#include <windows.h>

using namespace std;

void Function1(char *who)
{
        cout << who << " was here." << endl;
}

extern "C" {
void Podrobka(char *who)
{
        cout << "Who the fuck is " << who << "?" << endl;
}
}

extern "C" {
void wrapper(void);                // te wszystkie deklaracje wrappera
__asm(                             // służą temu żeby był on widoczny zarówno na poziomie kompilacji
		".globl _wrapper\n"        // przez gcc (deklaracja C++-owa) i na poziomie asemblerowego backendu
		"_wrapper:\n"              // (labele _wrapper:). Extern "c" zapobiega dekoracji kodu przez C++ i ułatwia odwoływanie się z asemblera.

		"push dword ptr [esp+8]\n" // magia :(
		"call _Podrobka\n"         // Jest to wrzucenie parametrów do funkcji 'podróbki'
		"add esp, 4\n"             // i wywołanie jej.

		"pop ecx\n"                // zachowanie adresu powrotu do wywołującej funkcji (czyli oryginalnej)

		"push ebp\n"               // te kilka operacji:
		"mov ebp, esp\n"           // ważne - wykonanie pierwszych operacji wykonywanych przez funkcję
                "sub esp, 8\n"             // są one nadpisane przez naszą 'tramp' więc trzeba je wykonać tutaj.
                "mov eax, dword ptr ss:[ebp+8]\n" // MOGĄ WYGLĄDAĆ INACZEJ DLA KAŻDEJ FUNKCJI, trzeba to sprawdzić za 
                                   // pomocą disassemblera

		"jmp ecx\n"                // powrót do wywołującej funkcji.
        );
}

void hooker(char *tramp, int t_size, DWORD addr)
{
 
    DWORD old;
    VirtualProtect((LPVOID)addr, t_size, PAGE_EXECUTE_READWRITE, &old);
 
    memcpy((LPVOID)addr, tramp, t_size);
 
    VirtualProtect((LPVOID)addr, t_size, old, &old);
}
 
int main()
{
        char tramp[] = {0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax addr
                        0xFF, 0xD0, // call eax (TYM RAZEM CALL.)
                        0x90, 0x90 }; // nop-y 
 
        DWORD addr_hook_wrapper = (DWORD)wrapper;
        DWORD addr_puts = (DWORD)Function1;
 
        memcpy(tramp + 1, &addr_hook_wrapper, 4);
        hooker(tramp, 9, addr_puts);
    
        Function1("Justin Bieber");
        cout << "wszystko OK";
        return 0;
} 

Tzn. Będzie działać na gcc i wymaga do kompilacji flagi -masm=intel

Ogólna zasada działania:

  1. sprawdzamy jak zaczyna się patchowana funkcja. W moim przypadku - tak:
004013EE  /$ 55             PUSH EBP
004013EF  |. 89E5           MOV EBP,ESP
004013F1  |. 83EC 08        SUB ESP,8
004013F4  |. 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
  1. Tworzymy trampolinę (dopełniamy ją NOP-ami żeby pasował ilością bajtów rozpoczęcia funkcji).

  2. Tworzymy wrappera - skomentowałem go najlepiej jak mogłem więc @seealso podany kod.

  3. Wrzucamy trampolinę, uruchamiamy, wszystko działa.

Trochę inaczej może to wyglądać w Visual Studio (jeśli używasz) - nie mam pod ręką więc nie przerobię chwilowo, ale trzeba przepisać wstawkę asemblerową (najlepiej wrzucić ją w funkcję typu naked).

0

Hm. Moze na poczatek zajmijmy sie pierwszym pytaniem, bo bardziej na tym mi zalezy. Te drugie opcjonalnie, wiec dajmy sobie na razie spokoj. A wiec. Kod assemblerowy w cudzyslowiu ktory podales nie jest przyjmowany przez kompilator visuala, z tego co wyczytalem jest to blad skladniowy coś jak np. deklaracja DW(double word). Ten blad tyczy sie wszystkich linii w cudzysłowie. Err: "inline assembler syntax error in 'opcode'; found 'bad token'". Dodawalem tokeny na koniec, ale nie pomaga.

Na poczatek, chcialbym sobie uproscic, a mianowicie funkcje nie beda nic przyjmowaly ani nic nie zwracaly. A wiec stos chyba nie jest tu potrzebny (mowie tu chyba bo nie znam za bardzo assemblera). Wykonalem dosc prymitywna operacje w wyniku czego otrzymalem swoista petla, a dokladniej wykonywane sa ciągle instrukcje funkcji "Podrobka". Troche mnie to dosc zdziwilo bo zadanie mialo na celu wywolac najpierw oryginalna a pozniej podrobiona funkcję razem wziętą. A wykonuje się tylko ta podrobiona, czyli dokładnie to co w poprzednim wątku było omawiane. Kod ktory jest ponizej wywoluje tylko funkcję 'Podrobka'. Dla mnie jest obojetne ktora funkcja prędzej zostanie wywołana, dla mnie ważne jest to aby obydwie zostaly uruchomione. A jeszcze jedno, tą "pętle" zatrzymac chcę.

void Function1()
{
	cout << "Running oryginal function1..." << endl;
}

void Podrobka()
{
	cout << "Who the fuck is Justin Bieber?" << endl;
};


void wrapper(void)
{
	__asm
	{
		call Podrobka;
		jmp Function1;
	}
}

void hooker(char *tramp, int t_size, DWORD addr)
{
 
    DWORD old;
    VirtualProtect((LPVOID)addr, t_size, PAGE_EXECUTE_READWRITE, &old);
 
    memcpy((LPVOID)addr, tramp, t_size);
 
    VirtualProtect((LPVOID)addr, t_size, old, &old);
}

int main()
{
    char tramp[8];
    tramp[0] = (char)0xB8; //mov eax, addr
    tramp[5] = (char)0xFF; tramp[6] = (char)0xD0; //call eax
    tramp[7] = (char)0x90; tramp[8] = (char)0x90; //nop-y
 
    DWORD addr_hook_wrapper = (DWORD)wrapper;
    DWORD addr_puts = (DWORD)Function1;
 
    memcpy(tramp + 1, &addr_hook_wrapper, 4);
    hooker(tramp, 9, addr_puts);

    Function1();
    getchar();
    return 0;
}

Sory, że dość mocno zmieniłem Twój kod, ale od bardziej prymitywnego chciałbym zacząć. Wracając.. jak to poprawnie zrobić?

0

Ten blad tyczy sie wszystkich linii w cudzysłowie. Err: "inline assembler syntax error in 'opcode'; found 'bad token'". Dodawalem tokeny na koniec, ale nie pomaga.

Cytując ostatnie zdanie w moim poście:

Trochę inaczej może to wyglądać w Visual Studio (jeśli używasz) - nie mam pod ręką więc nie przerobię chwilowo, ale trzeba przepisać wstawkę asemblerową (najlepiej wrzucić ją w funkcję typu naked).

Patrz również np. http://msdn.microsoft.com/en-us/library/5f7adz6y%28v=vs.80%29.aspx (naked jest zresztą tutaj konieczne nie 'zalecane')

Sory, że dość mocno zmieniłem Twój kod, ale od bardziej prymitywnego chciałbym zacząć. Wracając.. jak to poprawnie zrobić?

Widzisz, nie chodzi o to że ja chcę komplikować kod tylko o to że prościej się nie da. Jesli nie potrzebujesz parametrów, wyrzuć po prostu push i add esp przed twoja funkcja.

void wrapper(void)
{
        __asm
        {
                call Podrobka;
                jmp Function1;
        }
}

To że to działa to cud, gdyby nie twoje niezwykłe szczęście powinno wywalać twój program a u Ciebie robi tylko nieskończoną pętlę...

Pierwsze kilka bajtów funkcji jest nadpisywane przez tramp. Nie może działać funkcja której początek nie istnieje.
Musisz te operacje wykonać w trampolinie, przed wróceniem do funkcji.
Cytując KRZYCĄCY komentarz:

ważne - wykonanie pierwszych operacji wykonywanych przez funkcję
są one nadpisane przez naszą 'tramp' więc trzeba je wykonać tutaj.
MOGĄ WYGLĄDAĆ INACZEJ DLA KAŻDEJ FUNKCJI, trzeba to sprawdzić za pomocą disassemblera

Mój kod:

                "push ebp\n"               // te kilka operacji:
                "mov ebp, esp\n"           // ważne - wykonanie pierwszych operacji wykonywanych przez funkcję
                "sub esp, 8\n"             // są one nadpisane przez naszą 'tramp' więc trzeba je wykonać tutaj.
                "mov eax, dword ptr ss:[ebp+8]\n" // MOGĄ WYGLĄDAĆ INACZEJ DLA KAŻDEJ FUNKCJI, trzeba to sprawdzić za 
                                   // pomocą disassemblera
 

I jeszcze raz dwa pierwsze kroki:

Ogólna zasada działania:

  1. sprawdzamy jak zaczyna się patchowana funkcja. W moim przypadku - tak:

004013EE /$ 55 PUSH EBP
004013EF |. 89E5 MOV EBP,ESP
004013F1 |. 83EC 08 SUB ESP,8
004013F4 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]

  1. Tworzymy trampolinę (dopełniamy ją NOP-ami żeby pasował ilością bajtów rozpoczęcia funkcji).
0

Mówisz, że mam wypisać te instrukcje, które będą nadpisywane przez trampoline, czyli pierwsze kilka bajtów. W twoim przypadku 6 bajtów, a skąd mam wiedzieć ile u mnie? Może chodzi Tobie o 4 pierwsze instrukcje assemblerowe funkcji (te które jak mówisz tworzą kilka pierwszych bajtow). Jeżeli tak to u mnie wychodzi 9 bajtów. Ekhmm, chyba źle to zrozumiałem.

0

Musisz to sprawdzić przez deasemblację funkcji którą masz zamiar spatchować.

Parę przykładowych początków funkcji (z binarki stworzonej przez gcc):

00401315    /$ 55             PUSH EBP
00401316    |. 89E5           MOV EBP,ESP
00401318    |. 53             PUSH EBX
00401319    |. 83EC 14        SUB ESP,14
0040131C    |. 83E4 F0        AND ESP,FFFFFFF0
0040131F    |. B8 00000000    MOV EAX,0
004012D0    /$ 55             PUSH EBP
004012D1    |. 89E5           MOV EBP,ESP
004012D3    |. 83EC 08        SUB ESP,8
004012D6    |. 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
004012D9    |. 8845 FF        MOV BYTE PTR SS:[EBP-1],AL
00401800    |$ 55             PUSH EBP
00401801    |. 89E5           MOV EBP,ESP
00401803    |. 83EC 08        SUB ESP,8
00401806    |. 8B0D 20404000  MOV ECX,DWORD PTR DS:[404020]
0040180C    |. 85C9           TEST ECX,ECX
0040180E    |. 74 02          JE SHORT a.00401812

Pierwsze instrukcje (push ebp, mov ebp, esp, sum esp, xxx) to bardzo często się powtarzający motyw w skompilowanych programach - tak zwana ramka stosu.

Dla odmiany coś z msvcrt:

6FF6C5B9 pr> 6A 0C            PUSH 0C
6FF6C5BB     68 28C6F66F      PUSH msvcrt.6FF6C628
6FF6C5C0     E8 71D2FEFF      CALL msvcrt.6FF59836
6FF6C5C5     33C0             XOR EAX,EAX
6FF6C5C7     33FF             XOR EDI,EDI
6FF6C5C9     397D 08          CMP DWORD PTR SS:[EBP+8],EDI

Załóżmy że będziemy działać na tym:

00401315    /$ 55             PUSH EBP
00401316    |. 89E5           MOV EBP,ESP
00401318    |. 53             PUSH EBX
00401319    |. 83EC 14        SUB ESP,14
0040131C    |. 83E4 F0        AND ESP,FFFFFFF0
0040131F    |. B8 00000000    MOV EAX,0

Chcemy wykonać call do jakiejś swojej funkcji - czyli musimy na początek wrzucić asemblerowe mov eax addr; call eax. Taka instrukcja wygląda w heksach tak:

0xB8, 0x??, 0x??, 0x??, 0x??
0xFF, 0xD0

Czyli zajmuje 6 bajtów 7 bajtów. Nadpisujemy więc początek funkcji i otrzymujemy:

00401316       E8 5D43F411    CALL 12345678
0040131B       14             __Problem__
0040131C    |. 83E4 F0        AND ESP,FFFFFFF0
0040131F    |. B8 00000000    MOV EAX,0

Problemem jest ten bajt 0x14 - nie pasuje do żadnej instrukcji i na pewno spowoduje wywalenie się programu. Trzeba go więc zastąpić NOP-em.

00401316       E8 5D43F411    CALL 12345678
0040131B       90             NOP
0040131C    |. 83E4 F0        AND ESP,FFFFFFF0
0040131F    |. B8 00000000    MOV EAX,0

Jeszcze jeden problem - Ten patch usunął pierwsze inestukcje. Nie możemy tak po prostu usuwać operacji z kodu maszynowego, trzeba to naprawić - więc należy dodać usunięte instrukcje, tzn.

00401315    /$ 55             PUSH EBP
00401316    |. 89E5           MOV EBP,ESP
00401318    |. 53             PUSH EBX
00401319    |. 83EC 14        SUB ESP,14

Na koniec trampoliny.

0

Ok. Jeżeli początek mojej oryginalnej funkcji wygląda tak:

004114C0                 push    ebp
004114C1                 mov     ebp, esp
004114C3                 sub      esp, 0C0h
004114C9                 push    ebx

to mój wrapper powinien wyglądać mniejwiecej tak? (na razie program się wywala...). Nopy wypelnia trampolina.

void wrapper(void)
{
        __asm
        {

                call Podrobka

                pop ecx

                push ebp
		mov ebp, esp
		sub esp, 0Ch
		push ebx

		jmp ecx
        }
}
0

Skoro początek wygląda tak:

00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  83EC0C            sub esp,byte +0xc
00000006  53                push ebx

Masz tutaj już 7 wymaganych bajtów pamięci.

W takim razie nie musisz już nic dopisywać do trampoliny - musi mieć ona dokładnie 7 znaków.

0

Może będzie to na skróty, ale użyj Microsoft Detours :)

0
004114C0                 push    ebp
004114C1                 mov     ebp, esp
004114C3                 sub      esp, 0C0h
004114C9                 push    ebx

Tutaj jest 9 bajtow, a u ciebie nagle wzielo się 7. Skąd, skoro widać tylko 6 bajtów, dlaczego?

00000000  55                push ebp
00000001  89E5             mov ebp,esp
00000003  83EC0C         sub esp,byte +0xc
00000006  53                push ebx

^- 6 bajtow

Zrobiłem tak, ale wciąż się wywala:

void wrapper(void)
{
	__asm
	{
		call Podrobka

		pop ecx

		push ebp
		mov ebp, esp
		sub esp, 0xc0 //nie moge zrobic takiej operacji jak ty pokazales "byte + 0xC0"
		push ebx

		jmp ecx
	}
}

int main()
{
     char tramp[] = {0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax addr
						  0xFF, 0xD0}; // call eax
						 //0x90, 0x90 }; NOP-y nie sa wypelniane tak jak kazales
 
    DWORD addr_hook_wrapper = (DWORD)wrapper;
    DWORD addr_puts = (DWORD)Function1;
 
    memcpy(tramp + 1, &addr_hook_wrapper, 4);
    hooker(tramp, 7, addr_puts);

    Function1();
    getchar();
    return 0;
}
0

Tutaj jest 9 bajtow, a u ciebie nagle wzielo się 7. Skąd, skoro widać tylko 6 bajtów, dlaczego?

Faktycznie, moja wina - założyłem że jest to odejmowanie bajta (w którym 0xC0 się spokojnie mieści) ale twój kompilator wygenerował odejmowanie dworda który ma 4 bajty (instrukcja zajmuje więcej pamięci). (U mnie jest 7 bajtów, u ciebie jest 10 bajtów, razem z ostatnią instrukcją.)

Teraz dopiero dokładniej spojrzałem na twój poprzedni post.

void wrapper(void)
{
        __asm
        {
                call Podrobka
 
                pop ecx
 
                push ebp
                mov ebp, esp
                sub esp, 0xc0
                push ebx
 
                jmp ecx
        }
}

Cytując ostatnie zdanie w moim poście:

Trochę inaczej może to wyglądać w Visual Studio (jeśli używasz) - nie mam pod ręką więc nie przerobię chwilowo, ale trzeba przepisać wstawkę asemblerową (najlepiej wrzucić ją w funkcję typu naked).

Patrz również np. http://msdn.microsoft.com/en-us/library/5f7adz6y%28v=vs.80%29.aspx (naked jest zresztą tutaj konieczne nie 'zalecane')

Ech... czytasz w ogóle moje posty?

=======================================

Zakładając że funkcja faktycznie ma taki prolog - nie jestem w stanie przetestować bo nie mam nigdzie funkcji z odpowiednim prologiem.

__declspec( naked ) void wrapper(void)
{
        __asm
        {
                call Podrobka
 
                pop ecx
 
                push ebp  //
                mov ebp, esp  //
                sub esp, 0xc0 // razem 9 bajtów
 
                jmp ecx
        }
}
 
int main()
{
     char tramp[] = {0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax addr
                                                  0xFF, 0xD0}; // call eax
                                                 0x90, 0x90 }; // długość tramp == 9 bajtów
 
    DWORD addr_hook_wrapper = (DWORD)wrapper;
    DWORD addr_puts = (DWORD)Function1;
 
    memcpy(tramp + 1, &addr_hook_wrapper, 4);
    hooker(tramp, 9, addr_puts); // zapisujemy wszystkie 9 bajtów.
 
    Function1();
    getchar();
    return 0;
}
0

Cholerka.. Program nadal się wywala. Dla testu w trampolinie zamiast call'a (0xD0) użyłem jmp'a (0xE0) i program bez zadnych problemow funkcjonuje, ale wywolana jest tylko ta funkcja 'Podrobka' (widnieje napis 'Who the fuck..'). A oryginalna wcale nie ma zamiaru ruszyć. Masz moze pomysly co na to poradzic?

0

Przyznam szczerze że nie wierzyłem w Ciebie i myślałem że nie radzisz sobie z czymś prostym. Okazuje się jednak że ty dobrze kombinujesz, a to VS robi nas w... konia. (btw. używam VS 2008)

Napisałem prosty projekt w VS i chciałem przetestować czy działa.

// Tst.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>

using namespace std;
 
// ta funkcja symuluje dowolną inną funkcję z takim samym prologiem
__declspec( naked ) void Function1()
{
		__asm
        {
			 push    ebp
             mov     ebp, esp
             sub      esp, 0C0h
             push    ebx

			 // the stuff

			 pop ebx
			 add esp, 0C0h
			 pop ebp
		}
}
 
void Podrobka()
{
        cout << "Who the fuck is Justin Bieber?" << endl;
};

void hooker(unsigned char *tramp, int t_size, DWORD addr)
{
 
    DWORD old;
    VirtualProtect((LPVOID)addr, t_size, PAGE_EXECUTE_READWRITE, &old);
 
    memcpy((LPVOID)addr, tramp, t_size);
 
    VirtualProtect((LPVOID)addr, t_size, old, &old);
}

__declspec( naked ) void wrapper(void)
{
        __asm
        {
                call Podrobka
 
                pop ecx
 
                push ebp  //
                mov ebp, esp  //
                sub esp, 0xc0 // razem 9 bajtów
 
                jmp ecx
        }
}
 
int main()
{
    unsigned char tramp[] = { 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax addr
                                                  0xFF, 0xD0, // call eax
                                                 0x90, 0x90 }; // długość tramp == 9 bajtów
 
    DWORD addr_hook_wrapper = (DWORD)wrapper;
    DWORD addr_puts = (DWORD)Function1;
 
    memcpy(tramp + 1, &addr_hook_wrapper, 4);
    hooker(tramp, 9, addr_puts); // zapisujemy wszystkie 9 bajtów.
 
    Function1();
    getchar();
    return 0;
}

Cóż... Nie działa. Zdziwiłem się trochę, ale błądzić jest rzeczą ludzką i łatwo się czasami pomylić przy takich operacjach. Sprawdziłem więc kod asemblerowy dla tego programu i... zdziwiłem się drugi raz. W C++owym pseudokodzie wygląda to tak że adres funkcji np. Function1 tylko udaje adres tej funkcji, bo tak naprawdę wskazuje na funkcję w rodzaju

void pseudoFunction1() { Function1(); }

A my patchujemy właśnie tą pseudofunkcję (za pomocą pseudowrappera ofc) co prowadzi do dziwnych błędów. Taki kod to oczywiste marnowanie cykli procesora, więc pomyślałem że pewnie w trybie release tak nie będzie - a tu niespodzianka nr 3:

1>stdafx.cpp
1>Compiling...
1>Tst.cpp
1>Linking...
1>Generating code
1>d:\projects\c++\tst\tst\tst.cpp(38) : fatal error C1001: An internal error has occurred in the compiler.
1>(compiler file 'f:\dd\vctools\compiler\utc\src\p2\main.c[0xC6204E89:0xC6204E89]', line 182)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
1>Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1>LINK : fatal error LNK1000: Internal error during IMAGE::BuildImage

Żeby było śmieszniej, kompilator wywala się na linii

memcpy((LPVOID)addr, tramp, t_size);

Inaczej mówiąc, trafiłeś (trafiliśmy) na przeszkadzający feature w trybie debug (to akurat jeszcze można zrozumieć) i błąd w kompilatorze w trybie release... Trzeba mieć do tego niezłe szczęście, ale ty chyba je masz ;)

Dzisiaj nie mam siły się z tym męczyć, spróbuję coś z tym zrobić jutro (i zobaczę jak jest na VS 2010) - może trzeba będzie np. zrobić to brzydkim shellcodem zamiast ładną wstawką w assemblerze.

0

W C++owym pseudokodzie wygląda to tak że adres funkcji np. Function1 tylko udaje adres tej funkcji, bo tak naprawdę wskazuje na funkcję w rodzaju

void pseudoFunction1() { Function1(); }

Chodzi ci o to? :

004111BD ; void __cdecl Function1()
004111BD j_?Function1@@YAXXZ proc near                                    ; CODE XREF: _main+7Ep
004111BD                                                                                  ; DATA XREF: _main+53o
004111BD                 jmp     ?Function1@@YAXXZ ; Function1(void)
004111BD j_?Function1@@YAXXZ endp


004114C0 ; void __cdecl Function1()
004114C0 ?Function1@@YAXXZ proc near             ; CODE XREF: Function1(void)j
004114C0
004114C0 var_C0      = byte ptr -0C0h
004114C0
004114C0                 push    ebp
004114C1                 mov     ebp, esp
004114C3                 sub     esp, 0C0h

Tylko ta funkcja zdefiniowana przeze mnie ma taką konstrukcje. Dziwne, inne nie mają takiego coś w rodzaju "typedefa".

Dzisiaj nie mam siły się z tym męczyć, spróbuję coś z tym zrobić jutro (i zobaczę jak jest na VS 2010) - może trzeba będzie np. zrobić to brzydkim shellcodem zamiast ładną wstawką w assemblerze.

I tak kawał roboty odwaliłes. Solidny browar na ciebie czeka :)

0

I jak, udalo ci sie cos wykminic?

1 użytkowników online, w tym zalogowanych: 0, gości: 1