2010-11-12 11 views
10

Kendini değiştiren kod hakkında bir makale buldum ve bazı örnekler yapmaya çalıştım, ancak her zaman bölümleme hataları alıyoruz. Anlayabildiğim kadarıyla, bellek izinlerinde bir ihlal var. Kod bölümü (r) ead/e (x) olur ve bu nedenle yazma denemesi bu hataya neden olur. Programı, çalışma zamanında veya daha önce bellek izinlerini değiştirerek test etmenin bir yolu var mı? Linux kullanıyorum ve örnek GAS meclisinde yazılmıştır.Kendini değiştiren kod Linux'ta her zaman parçalanma hataları

.extern memcpy 
.section .data 
string: 
     .asciz "whatever" 
string_end: 
.section .bss 
     .lcomm buf, string_end-string 
.section .text 
.globl main 
main: 
     call changer 
     mov $string, %edx 
label: 
     push string_end-string 
     push $buf 
     push $string 
     call memcpy 
changer: 
     mov $offset_to_write, %esi 
     mov $label, %edi 
     mov $0xb, %ecx 
loop1: 
     lodsb 
     stosb 
     loop loop1 
     ret 
offset_to_write: 
     push 0 
     call exit 
end: 

işte osgx önerdiği değiştirildikten sonra bir çalışma kodudur. (Bunu çöküyor & bağlantı & koşmak araya ama öyle gdb kullanarak izlemek eğer kodunu değiştirir Aslında eğer!)

.extern memcpy 
.section .data 
string: 
     .asciz "Giorgos" 
string_end: 
.section .bss 
     .lcomm buf, string_end-string 
.section .text 
.globl main 
main: 
     lea (main), %esi    # get the start of memory region to 
             # change its permissions (smc-enabled) 
     andl $0xFFFFF000, %esi   # align to start of a pagesize 
     pushl $7      # permissions==r|w|x 
     pushl $4096     # page size 
     pushl %esi     # computed start address 
     call mprotect 

     call changer     # function that does smc 
     mov  $string, %edx 
label: 
     push string_end-string  # this code will be overridden 
     push $buf     # and never be executed! 
     push $string 
     call memcpy 
changer: 
     mov  $offset_to_write, %esi # simple copy bytes algorithm 
     mov  $label, %edi 
     mov  $0xb, %ecx 
loop1: 
     lodsb 
     stosb 
     loop loop1 
     ret 
offset_to_write:      # these instructions will be 
     push $0      # executed eventually 
     call exit 
end: 
+0

Linux'ta nasıl yapıldığından emin değilsiniz, ancak ya yönlendiriciye .text bölümü için özel bayraklar kullanma talimatı verebilirsiniz, ya kaynaklarda belirtilebilir (varsayılan değer .data RW'dir, çünkü .text RX'dir) – ruslik

+0

@ruslik Kaynaktan rwx kullanarak kod (metin) segmentinin iznini belirleyebilir miyim? –

cevap

14

Çalışma zamanında bellek erişim izinlerini değiştirmeniz gerekir.

#include <sys/mman.h> 

void *addr = get_address_of_instruction_pointer(); 
int length = 4096; /* size of a page */ 

if (mprotect(addr, length, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) { 
    /* current code page is now writable and code from it is allowed for execution */ 
} 
+0

Bu işlevi montajdan kullanabilir miyim? Kullanmak için herhangi bir özel ayrıcalığa ihtiyacım var mı? –

+1

Evet, yapabilirsin. Kolay bir şekilde C kodu mprotect ile .S dosyasına (-S) derlemeniz ve mprotect çağrısını kodunuza kopyalayıp yapıştırmanızdır. İşleminiz tarafından sahip olunan bellek için özel ayrıcalıklara gerek yoktur ve çekirdek için – osgx

+0

numaralı bir süper güvenlik yaması olmamalıdır. İyi bir makale (tek dezavantaj - intel sözdizimini kullanıyor) http: //asm.sourceforge. net/articles/smc.html – osgx

5

Modern CPU'lar, DEP olarak adlandırılan ve yığın üzerinde kod çalıştırılmasını engelleyen bir özelliğe sahiptir. Daha önce bu mümkün oldu; şimdi değil. İkili varsayılan olarak salt okunur belleğe yüklenir.

Bu arada, mROtect sistem çağrısını kullanarak binary'nizin konumunu bellekte yürütülebilir olarak işaretleyebilirsiniz - SO LONG AS YOUR CODE DEP-PROTECTED. Bu yüzden kod ve yığını koymaya çalışmayın ve sonra içine atlayın.

+1

'mprotect PROT_READ | PROT_WRITE | PROT_EXEC' DEP'yi devre dışı bırakmalıdır. Ayrıca, bu DEP sadece MS dünya – osgx

+0

denir Ama ben yığınını işlemek için çalışmıyorum, sadece kod bölümünde yönergeleri değiştirmek/oluşturmak için deneyin. –

+0

@osgx: _ "Bu, yalnızca MS dünyasında DEP olarak adlandırıldı" _ [Bu doğru değildir] (http://oleb.net/blog/2012/07/ios-hackers-handbook/); DEP ortak bir terimdir. –

1

Ayrıca bağlayıcı geçiş -N geçirerek tüm program için yazmaya karşı korumasını devre dışı bırakabilir. Bağlayıcıyı gcc'den çağırıyorsanız, Wl,-N'u geçin. Doğrudan ld'u çağırırsanız, -N'u geçirin.

İlgili konular