2012-11-16 20 views
5

Kullanılacak küçük bir C programım var. Ve ayrıca yapılacak olan saldırının arkasındaki mantığı da anladım. Ancak, çalıştığım kadarıyla, sadece benim için çalışmıyor. "Printf (user_input);"Biçim Dize Saldırısı

#include <stdio.h> 
#include <stdlib.h> 

#define SECRET1 0x44 
#define SECRET2 0x55 

int main(int argc, char *argv[]) { 
    char user_input[100]; 
    int *secret; 
    int int_input; 
    int a, b, c, d; /* other variables, not used here.*/ 

    /* The secret value is stored on the heap */ 
    secret = (int *) malloc(2*sizeof(int)); 

    /* getting the secret */ 
    secret[0] = SECRET1; secret[1] = SECRET2; 

    printf("Please enter a decimal integer\n"); 
    scanf("%d", &int_input); /* getting an input from user */ 
    printf("Please enter a string\n"); 
    scanf("%s", user_input); /* getting a string from user */ 

    printf(user_input); 
    printf("\n"); 

    /* Verify whether your attack is successful */ 
    printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2); 
    printf("The new secrets:  0x%x -- 0x%x\n", secret[0], secret[1]); 
    return 0; 
} 

Sadece adres ve gizli [0] biçim dizesi kullanarak değerini yazdırmak gerekiyor

"\ x6e \ xaf \ xff \ xff% x% x% x% x% s" gibi bir şey vermeye çalıştım. ama bu çalışmıyor. Herhangi bir öneri takdir edilecektir. Çok teşekkürler.

+1

Bir şeyin adresini yazdırmak isterseniz, muhtemelen, '&' operatörünün adresini kullanmalısınız. Iyi biçimlendirilmiş kod için –

+0

+1. –

cevap

8

Bu, bir sınıf için bir egzersiz gibi görünüyor, bu yüzden bazı işaretçiler vereceğim, ancak gerçek çözüm yok.

Güvenilir olmayan girişler sağlayarak bu programdan yararlanmaya çalışıyorsunuz. Burada iki tane oldukça açık böcek var; Biri arabelleğe taşıp yığının üzerine yazabildiğiniz için %s kullanarak scanf()'dur. Diğeri bir format-dize güvenlik açığıdır. Yığının üzerine yazılması, işlev döndürene kadar muhtemelen ilginç bir şey yapmanıza izin vermez. "Saldırının başarılı olup olmadığını doğrula" bölümüne dayanarak, büyük olasılıkla bu güvenlik açığından önce yararlanmak istersiniz, bu yüzden bir biçimlendirme dizisi güvenlik açığı olması gerektiğini tahmin ediyorum. Doğrulama bölümüne göre, secret tarafından işaret edilen belleğin üzerine yazmanız istenir. printf'un belleğe kontrollü bir konuma yazılmasına neden olmanın tek yolu, verilen göstericiyi yazan %n biçim belirtecini kullanmaktır.

Şimdi bu numara, uygun işaretçiyi bulana kadar yığınının yukarı doğru nasıl yukarı çıkacağını bulmaktır. Uygun şekilde, yığın üzerindeki işaretçiden hemen önce kullanıcı tarafından kontrol edilen bir tam sayı var. Bu yüzden, bir noktaya kolay bir sayı girebiliriz (belki de 65535, hex olarak ffff) ve yığınta ne olduğunu görmek için çok fazla %x s biçiminde bir biçim dizgisi kullanın. Bunu bulduğumuzda, yığındaki sonraki şey işaretçi olmalıdır.

Hmm. Bunu daha yeni denedim ve bunun çok basit olmadığını ortaya koyuyor. Yığın çerçevesinin tam düzeni aslında beyanların sırasına bağlı değildir; ve benim için farklı sistemler arasında farklılık gösteriyor. Bunun yerine, başlangıçta iyi bilinen bir dizeyle birlikte çok fazla %lx s kullanmalı ve gerçek işaretçiyi yazdırmak için bir satır ekledim, bu yüzden onu bulduğum zaman anlarım. Ardından ilgili işaretçiyi yazmak için ilgili %lx'u %n ile değiştirin. 20 ya da %lx s'yi denemek ve %n ile her birini tek tek değiştirerek bu işaretçinin üzerine yazmayı başarmanız en kolay olabilir. Her neyse, başlamanızı sağlamak için yeterli olduğunu umuyorum. Herhangi bir sorunuz olursa haberim olsun.

+2

Gerçekte, x86_64'de O2 veya O3 ile derlerseniz, arabellek dışında yığında herhangi bir şey bulunmayabilecek yeterli kayıt vardır. –

+0

Ayrıca, kullanılmayan değişkenler derleyici tarafından en iyi duruma getirilmiş olabilir, bu nedenle yığının gerçek kurulumu beklediğiniz gibi olmayabilir. –

+0

Girişleriniz için çok teşekkürler. Tekrar tekrar adres aldığımda, çoğu kez% 1x veririm. Yığında (yüksekten alçak) değişkenlerin sırayla, user_input, secret, int_input içinde saklandığını anlıyorum. Yani eğer% 1x 8 kez verirseniz, & int_input'a işaret edebilmem gerekir.Gizli = 0xbffffa5c, user_input = bffffa60, int_input = bffffa58 bir dize girin ondalık tamsayı girin % 1x% 1x% 1x% 1x% 1x% 1x% 1x% 1x bffffa60bffffa60bffffa584002c8a440021000400212d810 orijinal sırları: 0x44 - - 0x55 Yeni sırlar: 0x44 - 0x55 – shambolic