2015-01-25 2 views
3

Google은 악성 프로그램이 RAM에서 암호를 읽으려고합니다. 그래서 우리는 암호 변수를 덮어 쓴 다음 그것을 해제하는 함수를 작성했습니다. Clang이나 gcc 같은 스마트 컴파일러가이 함수 내부의 코드를 최적화 할 것이라는 점이 우리의 관심사입니다. 이 함수는 문자열의 모든 문자를 null 바이트로 변경 한 다음 변수를 해제합니다.clang/gcc는 암호 변수 지우기 기능을 최적화합니다

void free_pword(char* pword) { 
    char* pword_original = pword; 
    char c; 

    while ((c = *(pword++))) { 
     *pword = '\0'; 
    } 

    free(pword_original); 
} 

이제 우리의 질문입니다. 우리가 이것을해야합니까? 그렇지 않다면, 왜? 우리가 그것을 할 필요가 있다면, 어떻게 덮어 쓰기가 최적화되지 않을 것이라고 확신 할 수 있습니까?

########### 편집 1 : (2015 2월 11일) 미래에서

사랑하는 사람들 : 여기에 내가 바라 보았다

... 우리가 지금까지 알아 냈어요 무엇 원시 어셈블리 코드 (gcc에서)는 코드가 더 낫지 않느냐를 결정하기 위해 최적화 된 코드였습니다. 업데이트에서 옵티마이 저가 변경 될 경우 휘발성을 추가하기로 결정했습니다.

gcc의 버전이 테스트되었습니다.

$ gcc -v 
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1 
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn) 
Target: x86_64-apple-darwin14.1.0 
Thread model: posix 

나는 모든 컴파일러에서 안전하다는 것을 100 % 확신하지 못하기 때문에 자신의 대답을 만들고 받아들이지 않았습니다. 컴파일러에 대한 전문가가 확실하게 대답 할 수 있습니다.

해방 전에 암호를 안전하게 제거해야하는 경우 컴파일러를 사용하여이 기능을 테스트하고 원시 어셈블리를 살펴보십시오. 어셈블리를 이해할 필요없이 ___bzero 함수 (memset)와 _free 함수가 호출되었는지 확인하십시오.

현재 작업 버전 :

void free_pword(char * pword) { 
    //instead of changing the argument to the function, I added a volatile variable 
    //this was I don't have to change the calls to this function to remove warnings 
    char volatile * volatile_pword = pword; 
    memset((char *)volatile_pword, 0, strlen((char *)volatile_pword)); 
    free((char *)volatile_pword); 
} 
+3

최적화에 대한 첫 번째 해머는 '휘발성'입니다. 그런 다음 미묘함에 대해 생각할 수 있습니다. –

+0

암호 변환을 위해 별도의 번역 단위에서 함수를 호출하면 함수를 제거 할 수 있음을 알기 위해 더 많은 컴파일러가 필요합니다. 'memset()'또는 표시된 코드를 사용하면 옵티 마이저가 zapping 코드를 생략 할 수 있습니다. –

+0

BTW, 원래 코드는 버그가있어서 암호의 첫 번째 문자를 덮어 쓰지 않습니다. 'pword'는 이미'* pword = '\ 0';'실행될 때까지 증가했습니다. –

답변

1

컴파일러 멀리 memset에 대한 호출을 최적화하는 것이 전적으로 가능하다. 그렇기 때문에 memset_s (C11) 및 explicit_bzero (BSD)과 같은 기능이있어 메모리 블록을 안전하게 지울 수 있습니다.

는 또한 휘발성 함수 포인터를 사용하는 휘발성에 대한 포인터로 캐스팅보다 더 안정적이라고 생각 : asm 문 또는 메모리 장벽을 삽입하는 등의

void *(*volatile forced_memset)(void *, int, size_t) = memset; 

더 많은 트릭이 great thread on the musl mailing list에서 찾을 수 있습니다. 여기서도 흥미로운 post on how to portably test whether any of these approaches work에 대한 포인터를 찾을 수 있습니다.

관련 문제