2016-11-05 37 views
0

我有一個程序,目前似乎在Linux(Ubuntu 14.04)上運行正常,但在OS X(10.11.6)上運行時,我得到一箇中止陷阱6.我附加了我的代碼,但我懷疑問題實際上並沒有與特定的代碼綁定。這段代碼是用於一個類的項目,我實際上並沒有試圖破解密碼或任何東西。從OS X中的主返回時中止陷阱6但不是在Linux上

下面是代碼,我相信所有重要的東西都發生在main中。

#include <openssl/aes.h> 
#include <openssl/evp.h> 
#include <openssl/conf.h> 
#include <openssl/err.h> 


#define KEY_BYTES KEY_LENGTH/8 
#define KEY_LENGTH 128 


unsigned char* h(unsigned char* p, unsigned char* hp); 
void handleErrors(void); 
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, 
      unsigned char *iv, unsigned char *ciphertext); 


//assumes we've already padded with zeros 
unsigned char* h(unsigned char* p, unsigned char *hp){ 
    encrypt((unsigned char*)"0000000000000000", KEY_BYTES, p , (unsigned char*)"0000000000000000", hp); 
    return hp; 
} 

void handleErrors(void) 
{ 
    printf("panic!!\n"); 
    //ERR_print_errors_fp(stderr); //sg: throw a real error you fool! 
    abort(); 
} 

//sg: stolen from the evp man page 
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, 
      unsigned char *iv, unsigned char *ciphertext) 
{ 
    EVP_CIPHER_CTX *ctx; 

    int len; 

    int ciphertext_len; 

    /* Create and initialise the context */ 
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); 

    /* Initialise the encryption operation. IMPORTANT - ensure you use a key 
    * and IV size appropriate for your cipher 
    * In this example we are using 256 bit AES (i.e. a 256 bit key). The 
    * IV size for *most* modes is the same as the block size. For AES this 
    * is 128 bits */ 
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) 
     handleErrors(); 

    /* Provide the message to be encrypted, and obtain the encrypted output. 
    * EVP_EncryptUpdate can be called multiple times if necessary 
    */ 
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) 
     handleErrors(); 
    ciphertext_len = len; 

    /* Finalise the encryption. Further ciphertext bytes may be written at 
    * this stage. 
    */ 
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); 
    ciphertext_len += len; 

    /* Clean up */ 
    EVP_CIPHER_CTX_free(ctx); 

    return ciphertext_len; 
} 


int main(){ 

    /* Initialise the library */ 
    ERR_load_crypto_strings(); 
    OpenSSL_add_all_algorithms(); 
    OPENSSL_config(NULL); 

    EVP_CIPHER_CTX *ctx; 
    unsigned char hp[KEY_BYTES]; 

    /* Create and initialise the context */ 
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); 

    h((unsigned char*) "1111111111111111", hp); 

    for(int i = 0; i < KEY_BYTES; i++){ 
     printf("h(%i) = %x\n", i, hp[i]); 
    } 

    return 0; 
} 

在Linux上運行,我得到以下(這是我所期望的)

h(0) = 10 
h(1) = df 
h(2) = c1 
h(3) = b5 
h(4) = f6 
h(5) = 6c 
h(6) = fd 
h(7) = 6a 
h(8) = 1d 
h(9) = c4 
h(10) = 6d 
h(11) = 66 
h(12) = 90 
h(13) = 7b 
h(14) = ee 
h(15) = b1 

然而,當我在OS XI運行得到如下:

h(0) = 10 
h(1) = df 
h(2) = c1 
h(3) = b5 
h(4) = f6 
h(5) = 6c 
h(6) = fd 
h(7) = 6a 
h(8) = 1d 
h(9) = c4 
h(10) = 6d 
h(11) = 66 
h(12) = 90 
h(13) = 7b 
h(14) = ee 
h(15) = b1 
Abort trap: 6 

當我彈出這到gdb我得到以下

(gdb) r 
Starting program: /Users/sgillen/Code/457/proj3/a.out 
h(0) = 10 
h(1) = df 
h(2) = c1 
h(3) = b5 
h(4) = f6 
h(5) = 6c 
h(6) = fd 
h(7) = 6a 
h(8) = 1d 
h(9) = c4 
h(10) = 6d 
h(11) = 66 
h(12) = 90 
h(13) = 7b 
h(14) = ee 
h(15) = b1 

Program received signal SIGABRT, Aborted. 
0x00007fff93150f06 in __pthread_kill() from /usr/lib/system/libsystem_kernel.dylib 
(gdb) where 
#0 0x00007fff93150f06 in __pthread_kill() from /usr/lib/system/libsystem_kernel.dylib 
#1 0x00007fff97b374ec in pthread_kill() from /usr/lib/system/libsystem_pthread.dylib 
#2 0x00007fff9ba8077f in __abort() from /usr/lib/system/libsystem_c.dylib 
#3 0x00007fff9ba8105e in __stack_chk_fail() from /usr/lib/system/libsystem_c.dylib 
#4 0x0000000100000ea9 in main() at gen_table.cpp:90 

不知道如何在堆棧溢出上做行數,但gen_table.cpp的第90行是最後一次在main中返回0。

我編譯我的代碼與以下,如果這是相關的。

clang -Wall -std=c++11 gen_table.cpp -I/usr/local/opt/openssl/include/ -lcrypto -lssl -g 

任何幫助將不勝感激,謝謝!

+1

程序中的某些東西可能會導致未定義的行爲。使用像valgrind這樣的工具來檢測內存損壞。 – Barmar

+0

你有'KEY_BYTES'和'KEY_LENGTH'定義錯誤的順序。 – Barmar

+0

感謝Barmer的評論。我已經在程序上運行了valgrind,並且沒有任何錯誤或警告(如果您願意,我可以向您顯示確切的輸出)。在這種情況下訂單不重要嗎?我的理解是預編譯器將運行並用KEY_LENGTH/8替換KEY_BYTES,然後運行並用128/8代替KEY_LENGTH/8。如果我在那裏錯了,請糾正我,或者如果以相反的順序使它更有效。另外,如果有更好的方法來回復堆棧溢出的評論,請不要猶豫,讓我知道。 – sgillen

回答

0

我找到了我的問題的答案我想我會爲任何其他遇到同樣問題的人發佈答案。問題是我覆蓋了我自己的堆棧。我使用的加密函數實際上是寫32個字節到hp(這是一個16字節的unsigned char居住在堆棧上)。所以我會銷燬我自己的堆棧,但不寫入任何不屬於我的進程的內存。這導致沒有seg故障,但是當程序試圖返回時最終出現問題。殺死我的確切的事情取決於我如何編譯我的代碼。

我其實很驚訝valgrind沒有抓住這個。而我仍然不知道爲什麼它似乎在linux編譯時用clang編譯(使用g ++編譯我得到了一個堆棧粉碎檢測到的錯誤)。

編輯: 要明確的解決辦法是解決我的加密實現,以便它只寫入16個字節。我只是通過評論EVP_EncryptFinal_ex調用來做到這一點。

+0

什麼是修復? – Barmar