Assembler - Opcody problem

Odpowiedz Nowy wątek
2012-08-13 03:34
0

Witam, otóż chcę zmodyfikować opcode w pamięci procesu, w tym samym procesie, żeby w trakcie działania wykonała się inna instrukcja. Przy segmencie danych to działa, jednak jak próbuję z segmentem kodu to program mi się crashuje. Nie wiem czy źle modyfikuję instrukcję, czy wynika to z ograniczenia OS. Prosiłbym o pomoc.

00401000 B8 05 MOV EAX, 5
...

mov al, 0BBh
mov ebx, 0401000h
mov cs:[ebx], al

Pozostało 580 znaków

2012-08-13 03:41
0

przeczytaj wiadomosc na gg


░█░█░█░█░█░█░█░█░█░█░█░

Pozostało 580 znaków

2012-08-13 06:26
0

Pogadalem z nim i wiem juz o co chodzi w uproszczeniu problem wyglada tak:

Mamy prosty kod w C++:

#include <cstdio>

extern "C"
{
  char* test();
}

int main()
{
  printf("%s\n", test());
  printf("%s\n", test());
  return 0;
}

I kod w ASM (kompilator: NASM):

global  _test

segment data

text1: DB "krzysiu1", 0
text2: DB "krwq", 0

segment code
input_start:
    mov eax, text2
input_end:

_test:
        push    ebp 
        mov     ebp, esp 

    output:
    mov eax, text1

    mov esi, input_start
    mov edi, output
    mov ecx, input_end-input_start
    cld
    rep movsb

    leave
    ret

chcialem zeby kod zmodyfikowal sam siebie zamieniajac instrukcje "mov eax, text1" na "mov eax, text2" (uproszczony przypadek, w ogolnosci po prostu ma kopiowac input do output, z zalozeniem ze oba maja taki sam rozmiar).

Po zlinkowaniu i odpaleniu output programu ma wygladac tak:

krzysiu
krwq

z asm jestem cienki. moge tylko powiedziec ze powyzszy kod sie crashuje i nie mam pomyslu jak to naprawic, moglby ktos pomoc? Czy moj kod jest bledny czy OS nie pozwala na modyfikacje segmentu .CODE? jesli opcja numer 2 to jak temu zapobiec? da sie jakos zezwolic na modyfikacje segmentu?


░█░█░█░█░█░█░█░█░█░█░█░
edytowany 1x, ostatnio: krwq, 2012-08-13 06:30

Pozostało 580 znaków

2012-08-13 09:48
Rev
5

W przypadku Windows sekcja kodu jest faktycznie specjalnie chroniona. Żeby umożliwić zmodyfikowanie kodu trzeba:

  • wywołać funkcję VirtualProtect (za pomocą ostatniego argumentu najlepiej zapisać sobie poprzednią wartość)
  • zmodyfikować kod
  • przywrócić poprzednie uprawnienia
  • wywołać FlushInstructionCache

http://msdn.microsoft.com/en-[...]op/aa366898%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-[...]op/ms679350%28v=vs.85%29.aspx


+1 za FlushInstructionCache, to się nazywa porządne programowanie! Aczkolwiek na architekturach x86 i x64, a podejrzewam że na takich autor pytania siedzi, nie są konieczne - cytując MSDN FlushInstructionCache is not necessary on x86 or x64 CPU architectures as these have a transparent cache.. - msm 2012-08-13 11:57
@MSM&quot; to jest tylko czyjś komentarz, nie część artykułu na MSDN. poza tym jeśli "a jump instruction is sufficient to serialize the instruction prefetch queue" to dla św. Spokoju niech będzie to skok do FlushInstructionCache(). - Azarien 2012-08-15 11:26

Pozostało 580 znaków

2012-08-13 16:45
0

chyba jednak z ASM dalej mam cos nie tak. Tutaj aktualny kod:
CPP:

#include <cstdio>
#include "windows.h"

extern "C"
{
  char* test();
  void* test_address();
  size_t test_size();
}

int main()
{
  DWORD old_prot,foo;
  void* address = test_address();
  size_t size = test_size();
  VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &old_prot);

  printf("%s\n", test());
  printf("%s\n", test());
  VirtualProtect(address, size, old_prot, &foo);
  FlushInstructionCache(GetCurrentProcess(), address, size);

  return 0;
}

ASM:

global  _test
global  _test_address
global  _test_size

segment data

text1: DB "krzysiu1", 0
text2: DB "krwq", 0

segment code
input_start:
    mov eax, text2
input_end:

_test:
        push    ebp 
        mov     ebp, esp 

output_start:
    mov eax, text1
output_end:

    mov esi, input_start
    mov edi, output_start
    cld
    mov cx, input_end-input_start
    rep movsb

    leave
    ret

_test_address:
    mov eax, output_start
    ret

_test_size:
    mov eax, output_end-output_start
    ret

░█░█░█░█░█░█░█░█░█░█░█░
edytowany 1x, ostatnio: krwq, 2012-08-13 16:45
wydaje mi sie ze problem moze byc z tym ze tam trzeba podac poczatek strony bloku pamieci a nie mojego kodu, ale nie mam pojecia skad ta informacje wziac - krwq 2012-08-13 16:47

Pozostało 580 znaków

2012-08-13 19:30
Rev

Sorki, że nie poprawiłem twojego kodu, ale tak źle się czuję, że tylko wkleję ci to, co wcześniej sam naskrobałem.
Visual Studio + Masm

#include <iostream>
#include <Windows.h>

extern "C" char* TestFunc();
extern "C" size_t GetTestFuncLength();
extern "C" void ModifyTestFunc();

int main()
{
    size_t testFuncLength = GetTestFuncLength();
    DWORD oldProtect;

    std::cout << "TestFunc(): " << TestFunc() << "\n";

    VirtualProtect(&TestFunc, testFuncLength, PAGE_EXECUTE_READWRITE, &oldProtect);
    ModifyTestFunc();
    VirtualProtect(&TestFunc, testFuncLength, oldProtect, &oldProtect);
    FlushInstructionCache(GetModuleHandle(NULL), &TestFunc, testFuncLength);

    std::cout << "TestFunc(): " << TestFunc() << "\n";

    return 0;
}
.386
.model flat, c
.stack

.data

Text1 db "test1", 0
Text2 db "test2", 0

.code

InputStart:
    mov eax, offset Text2
InputEnd:

TestFunc proc
    mov eax, offset Text1
    ret
TestFunc endp
TestFuncEnd:

GetTestFuncLength proc
    mov eax, TestFuncEnd - TestFunc
    ret
GetTestFuncLength endp

ModifyTestFunc proc
    mov esi, InputStart
    mov edi, TestFunc
    mov ecx, InputEnd - InputStart

    cld
    rep movsb
    ret
ModifyTestFunc endp

end

edytowany 1x, ostatnio: Rev, 2012-08-13 19:32
nie rozumiem czemu ten kod Ci dziala a ten moj nie, przeciez one sa praktycznie identyczne, chyba ze zaraz po modyfikacji nie mozna odpalac kodu, to wtedy by to mialo sens. jak wroce do domu to sprawdze czy taka zmiana pomoze. Dzieki @Rev! :) - krwq 2012-08-13 20:29
dziala o_O jedyne roznice byly takie ze w wersji numer 1 modyfikowanie odbywalo sie w tym samym miejscu i adres miejsca modyfikacji byl zwracany przez inna funkcje - krwq 2012-08-14 03:15

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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