이전 기사인 PHP 암호화 파일의 실용적인 복원에서 PHP의 파일 암호화 방식의 단점을 발견했다고 언급하여 이 기사를 작성하게 되었습니다.
배경 분석
우리 모두 알고 있듯이 PHP는 스크립팅 언어이며, 스크립팅 언어는 주로 컴파일 대신 해석을 사용합니다. 그래서 컴파일된 언어(C, C#, C++)에 비해 exedll을 직접 생성하는 기능은 없습니다. 따라서 기존의 암호화 방법을 사용할 수 없습니다.
따라서 PHP에는 일반적으로 난독화와 암호화라는 두 가지 암호화 방법이 있습니다.
난독화는 엄밀한 의미에서 암호화가 아닙니다. 이런 종류의 코드는 병음 약어를 사용하여 변수 이름을 지정하는 코드와 비슷하지만 조금 더 힘들어 보입니다. 이것은 우리의 논의 범위를 벗어납니다.
암호화는 두 가지 방법으로 수행됩니다. 하나는 확장 프로그램(Loader)을 사용하는 것입니다. 다른 하나는 확장이 없습니다.
먼저 확장하지 않고 암호화하는 방법에 대해 말씀드리겠습니다. 이 암호화 방법은 해독 프로세스가 공개되어 있고 알려진 PHP 기능을 사용해야 하기 때문에 매우 지능적이지 않습니다. 암호화된 코드는 일반적으로 다음과 같습니다.
<?phpeval(base64_decode("cGhwaW5mbygpOw=="));
매우 복잡해 보이더라도
는 위 코드의 변형일 뿐입니다. 이 암호 해독 양식은 노출되면 해독하기가 매우 쉽습니다. eval을 찾아 echo로 변경하면 됩니다.
다른 확장 방법은 더 복잡합니다. 여기서 확장의 기능은 주로 코드를 해독하고 실행하는 것입니다. 비확장 형식에 비해 확장에 해독 및 실행 코드가 숨겨져 있으므로 크래킹이 더 복잡합니다.
여기의 확장은 일반적으로 두 가지 유형으로 나뉩니다. 1. 복호화 실행 기능을 제공하는 확장입니다. 2. 사용자 정의 PHP 파일을 구문 분석하는 기능을 구현하려면 zend_compile_file을 직접 덮어씁니다.
첫 번째이자 가장 일반적인 예는 지난 기사에서 언급한 zoeeyguard로, 주로 zend_eval_string 함수를 사용하여 PHP 코드를 실행합니다.
두 번째 유형의 대표자는 Zend Guard와 Song Ge의 php-beast입니다.
두 가지 크래킹 아이디어는 비슷하다고 할 수 있다. 이전 기사의 아이디어를 우선적으로 시도해 볼 수 있습니다.
물론, 이전 글에서 문제를 해결하지 못했다면 어떨까요?
이때에는 대형 킬러무기를 사용해야 합니다.
이전 기사에서 zend_compile_file 및 zend_eval_string 두 가지 함수에 대해 이야기한 것을 보실 수 있을 것입니다. 일부 똑똑한 PHP 사용자는 이미 이에 대해 생각해 본 적이 있을 것입니다. 아이디어는 여전히 eval을 찾아서 echo로 변경하는 것입니다.
실제 사례
아무것도 하지 않고 말만 할 수는 없습니다. 예를 들어보겠습니다.
이번에는 송 형제의 php-beast부터 시작하겠습니다. 송 형제의 코드는 매우 아름답게 작성되었습니다. AES DES 암호 해독에 시간이 걸린다는 것을 알고 그는 캐시를 작성했습니다.
1. Linux용 PHP 소스 코드 패키지를 다운로드합니다(5.6과 5.5 중 하나를 선택하는 것이 가장 좋습니다. 7은 지원되지 않습니다. 참고: 7의 변경 사항은 꽤 큽니다. 호환되지 않는 것이 많습니다. Zend Guard 7도 지원되지 않습니다. 여기서는 우회했습니다.)
2. Zendzend_언어_scanner.c 파일에서 다음과 같은 함수를 찾습니다: zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) 다음 코드를 앞에 추가하세요(코드가 잘못 작성되었으니 불평하지 마세요):
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { zend_lex_state original_lex_state; zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); zend_op_array *original_active_op_array = CG(active_op_array); zend_op_array *retval=NULL; int compiler_result; zend_bool compilation_successful=0; znode retval_znode; zend_bool original_in_compilation = CG(in_compilation); /** BEGIN **/ //加在这里的含义就是每次php编译php源码的时候都把这份源码打印一份 char *buf; size_t size; zend_stream_fixup(file_handle, &buf, &size); printf("\n#######\nFILE TYPE: %d FILE NAME: %s CONTENT: %s\n#######\n", (*file_handle).type, (*file_handle).filename, buf); /** END **/
php 폴더에서 실행:
//节省点时间 ./configure --disable-ipv6 --disable-all make make install
4. , PHP가 성공적으로 설치되었습니다.
5. 두 개의 테스트 파일을 작성합니다. 함수는 다음과 같습니다. test.php는 이를 실행하여 before.php를 암호화하여 after.php를 생성합니다.
//test.php <?php $path = __DIR__ . '/before.php'; $newPath = __DIR__ . '/after.php'; $result = beast_encode_file($path, $newPath, 0, BEAST_ENCRYPT_TYPE_DES); var_dump($result);
//before.php <?php print 'http://wx-app.com.cn/' . PHP_EOL;
7. 다음 php test.php를 실행한 후 php after.php를 실행합니다.
아래 스크린샷을 보세요:
요약
1. 풀 수 없는 비밀번호는 없습니다. 우리가 할 수 있는 일은 크래킹 시간을 늘리는 것 뿐이다. 크래킹 시간이 개인의 수명보다 길다면 이 암호화 방법은 확실히 성공한 것입니다.
2. 암호화된 프로그램의 경우 크래커가 작성자의 생각을 이해하고 추측해야 하는 것처럼 작성자도 크래커의 방법과 수단을 이해해야 합니다. 이런 방법으로만 우리는 크래킹하기 더 어려운 프로그램을 작성할 수 있습니다.
3. 암호화에 비해 PHP 소스 코드의 "암호화"에는 난독화가 더 적합하다고 생각합니다.
4. PHP 코드를 암호화하여 게시하려면 수수료를 늘리고 소스 코드를 직접 제공하는 것이 가장 좋습니다.