C Write php extension under Windows (Encrypt and decrypt PHP source code)
First hackers with Hello World.
Download the PHP source package, ext directory is the extension directory, there are 2 important files are Ext_skel and ext_skel_win32.php.
Download Cygwin. With this you can easily create PHP extensions under Windows.
Download ...
After download, use PHP ext_skel_win32.php--extname=hello to compile and build our extended development directory Hello
And then start writing the test program Hello World
Add function definitions and function registration statements in the HELLO.C file:
Function Registration Statement: const Zend_function_entry hello_functions[] = {
? Php_fe (confirm_hello_compiled, NULL)?
??? Php_fe (Sayhello,null)//This sentence is the one we added manually
? {null, NULL, NULL}
};
function definition: php_function (SayHello) {
php_printf ("Hello C extension");
}
It seems that it is important to have a macro form that appears in Php_function, because a naming conflict or other conflict can occur if you write the C code directly.
Then add the function declaration statement inside the Php_hello.h: php_function (SayHello);
Write the test program, compile the results appear. /main/config.w32.h ': No such file or directory
Check online, as if to download additional packages ... Oh, trouble.
Http://www.php.net/extra/bindlib_w32.zip
Http://www.php.net/extra/win32build.zip
Put these two packages together and I'll put them in the Win32/build directory
Then execute PHP source package root directory Buildconf.bat (preferably run at the command line, otherwise the results will be flashed)
Then set the Bison.exe (inside the package that you just downloaded) to the environment variable, and then run Configure.bat. This file is generated after the/main/config.w32.h is finished.
Then compile again just now the Hello project results a big push error.
Shaped like:.. \.. \main\streams/php_stream_transport.h: Error c2143:syntax error:missing ') ' before ' * '
.. \.. \main\streams/php_stream_transport.h: Error C2081: ' socklen_t ': name in formal parameter list illegal
Online said is because the macro definition can not find this, it should be socklen_t this macro is not defined, but its specific macro definition should be what kind of, always can not write a bar.????????? So open \main\streams/php_stream_transport.h discovery should be a type alias, and an int, because socklen_t addrlen;addrlen is literally the value of the stored length.
So add typedef int socklen_t to this file; save
In the compilation of the project just now, the error is much less, but there are 7, after the inspection found that the Chinese symbol was entered. Correct re-compiling ... There is one more error:
Link:fatal error Lnk1181:cannot Open input file "Php5ts.lib"
You will then find php5ts.lib this file and put it in the project directory or VC6 lib file under the default search directory. Find, find, find ...
TMD, with Windows Search for a long time have not found. Baidu is said to be inside the PHP binary code package. So first the next version of the binary code package (it should be the usual PHP to download the package that must be downloaded)
Let's start with the environment. windows+vc6+php5.3.5 (binary code package and source package) +cygwin
Download complete, find, copy, compile, success!
But there was a very serious problem, DLL file didn't come out, and, I cried
The Php_hello.exp and Php_hello.lib are created. How can it be static??
In fact, it has been generated, but not in this directory under the Release_ts directory, but in the Ext Superior release_ts directory.
Then test. Haha, say is undefined function, is it possible to test the PHP version and my extension of the PHP version of the relationship?
Test a bit is not, as long as the INI in a set load Php_hello.dll reboot Apache will appear memory unreadable error.
Always feel that the code is not a problem, it should be the previous configuration compile the time there is a problem.
After a few tests found that the PHP binary package under the wrong I under the vc9 should be under the VC6.
?
The next step is to start writing encryption and decryption. The encryption and decryption algorithm itself is not the focus here, the focus is how to Zend layer with the interface of the Zend itself and C to program, before Zend compile the source file to decrypt the file (of course, before the file is encrypted). For ease of use. My idea is to build a DLL like Php_screw and generate an encrypted executable file that is executed manually by us, passing in the directory parameters and being able to encrypt all the files in that directory.
After looking for a bunch of information on the Internet, and then look at Php_screw code, there are some difficulties, so decided to write according to their own ideas. Of course, some places will draw on Php_screw code
The first is to write a function to decrypt the file. This function decrypts the contents of the file using our existing decryption algorithm.
This function should have a parameter to receive the current request file handle (seemingly zend_compile_file this thing, Baidu, confirm, a few articles said is a function pointer, I saw the next source code is really a function pointer) Externzend_api ZEND_OP_ Array * (*zend_compile_file) (zend_file_handle*file_handle, int type TSRMLS_DC);
So how do you get the file pointer for the current request file? It may be related to the function that the Zend_compile_file function pointer refers to. Zend_compile_file=compile_file was found in the source code, the definition of the function is zend_language_scanner.c, but to understand the function is a bit difficult, the online statement is:
-------------
The zend_compile_file is responsible for compiling the script file to be executed into the OP codes consisting of the ze basic instruction sequence.
PHP executes this code in the following 4 steps:
1. Scanning (lexing), convert the PHP code to a language fragment (Tokens)
2. Parsing, convert tokens to simple and meaningful expressions
3. Compilation, compile the expression into Opocdes
4. Execution, execute opcodes sequentially, one at a time, thus realizing the function of PHP script.
-------------
So we should be able to decrypt the file before this four step.
The idea is to rewrite a function A to determine if the file is decrypted before it is compile, and then call the default Complie function. Once you have defined function A, you should pass function A to the function pointer when the request is initialized Zend_compile_file
Php_minit_function (Dencrypt) {
? old_comlie_file =zend_complie_file;//Keep the default compile to wait for the call
? zend_complie_file = function A;
? return SUCCESS;
}
Zend_api Zend_op_array *a (zend_file_handle *file_handle,int typetsrmls_dc) {//TSRMLS_DC here is a macro similar to,... (The definition of the macro is temporarily missing) in short, it is related to the thread safety of global variables in multi-threaded environment.
? Decrypt code ...
? Old_comlie_file (File_handle);
?....
}
But the problem is still not solved, because we still do not know how to get to the file pointer. I see the php_screw inside the decryption procedure is very long, the reference ... The FP =fopen (File_handle->filename, "R") was found, and the original File_handle contains the file name information (in fact, if you find the structure of File_handle definition statement will know).
But there's a php_screw inside.
CHAR?FNAME[32];
? memset (fname, 0, sizeof fname);
if (zend_is_executing (Tsrmls_c)) {//tsrmls_c Get global variables
?? if (Get_active_function_name (Tsrmls_c)) {//Gets the name of the current calling function (the current calling function?) Where's the function? PHP functions? Think of course the function inside the Zend. Instead of the PHP layer's function, because it's not compiled yet, and it's not done yet.
??? strncpy (Fname,get_active_function_name (tsrmls_c), sizeof fname-2);
??}
?}
? if (Fname[0]) {
?? if (strcasecmp (fname, "show_source") = = 0//that is, if both functions are present, they are not compiled. Well, it looks right.
??? || STRCASECMP (fname, "highlight_file") = = 0) {
??? Returnnull;
??}
?}? So this paragraph is still necessary, or meet the above two functions can not be achieved, compile_file function inside should also have this step to. So the main point here is not to let it be decrypted, but to display the ciphertext directly.
There's this one.
? fp = fopen (File_handle->filename, "R");
if (!FP) {//If open fails, call the default compile function directly
?? Returnorg_compile_file (File_handle, type);
?}
? fread (buf, Pm9screw_len, 1,FP);//The function of the 5 sentence is: If the found unencrypted file is not decrypted.
? if (memcmp (buf, Pm9screw, pm9screw_len)! = 0) {
?? Fclose (FP);
?? Returnorg_compile_file (File_handle, type);
?}
?
if (File_handle->type ==zend_handle_fp) fclose (FILE_HANDLE->HANDLE.FP);//Determine the file handle type, apply the corresponding close function.
? if (File_handle->type ==zend_handle_fd) Close (FILE_HANDLE->HANDLE.FD);
?
FILE_HANDLE->HANDLE.FP =pm9screw_ext_fopen (FP);//Call the function that decrypts the file and return the result with the FP receive function inside the File_handle
? file_handle->type =zend_handle_fp;//Sets the handle type to the file pointer type
? File_handle->opened_path =expand_filepath (File_handle->filename, NULLTSRMLS_CC);//Here is a bit of a wonder, guess whether to accept the path of the current file? Traced all the way to expand_filepath_ex. The last sentence of this function is returnreal_path; it looks like it's going to be the path to the file currently being compiled. But why should there be two steps above? is to set the type and path of the two. If we do not do the decryption operation without these two steps, my guess is because fclose (FILE_HANDLE->HANDLE.FP) here changed the state of File_handle, so only need to reset it!
(But one question is, is this to be decrypted before compilation, or before scanning?) I initially think that semantically is compilation before the decryption, but from the actual situation should be decrypted before scanning, this side can be verified later, it turns out that the latter is right, because Compile_file function has a pair of open_file_for_ The invocation of the scanning function, which means that the previous 123 steps are performed in the Compile_file function)
The entry point is there (there are 4 3 problems to be solved).
The next step is to write the function that decrypts the file
The problem to consider is that the plaintext code after decrypting the file does not need to be written to the file, so how do you get these plaintext file pointers? Use temporary files to do it? However, if each request uses a different temporary file that generates a lot of temporary files (which is obviously not possible), there will be a resource waiting issue (obviously not possible) if you use only one temporary file for different requests to the same PHP file. Can you specify a file pointer directly in memory? Take a look at Php_screw's practice, call tmpfile () to produce temporary files, but will be automatically deleted when the program exits! In fact, I think the files in memory are also implemented in this way.
Directly down to the previous use of PHP to write the reversible encryption and decryption algorithm with C to achieve, but C has no ready-made MD5 and Base64 functions, it seems only to abandon the 2.
After writing it began to compile, encountered a number of errors are also changed over.
Then the link comes up with an error: Error lnk2001:unresolved external symbol_zend_compile_file
Search, it seems that the function is not compiled in the same way caused by the function can not be found to join
Begin_extern_c ()
Zend_api Zend_op_array * (*zend_compile_file) (zend_file_handle*file_handle, int type TSRMLS_DC);
End_extern_c ()
Can
Building the DLL file succeeds, but does not know how to generate an executable file for encryption, the simplest solution is to build another project. It seems to have to do this, because some of the VC compiler mechanism and parameter settings are not very familiar with (later to study the programmer's self-cultivation seems to have said this)
Then encountered the C pointer transfer problem (long time did not get, some basic forget, and finally use a two-level pointer to solve the problem of the pointer as a parameter callback)
There was a problem with the _zend_compile_file symbol when I encountered the link (related to ZEND_API macro dllimport\dllexport)
And then encountered the problem of reading and writing files, in fact, it is true that I write the ciphertext to the file manually copied to another file to test, the results will be wrong, if you copy the file directly, or directly manipulate the original file is correct.
Finally encountered a memory unreadable error ...
Finally, the discovery is due to the problem of file read mode, binary reading is possible, if read and write in text, some special characters will be processed.
... The final Test function is yes, but if you really want to apply it to improve, such as when I encrypt the original directory directly generated encrypted files, better practice should be to the original PHP files packaged, easy to manage.
The next step was to get the ZF framework, and it was almost forgotten, and there was still a lot of stuff that didn't work.
?
=======================================
Original address:
Http://blog.sina.com.cn/s/blog_4d06da1f0100pgmj.html
Http://blog.sina.com.cn/s/blog_4d06da1f0100pni3.html
?
?
=======================================
Related references:
Write the C extension for PHP under Windows:
http://koda.iteye.com/blog/315779
?
To extend your PHP with C + +:
Http://www.laruence.com/2009/04/28/719.html
?
?
Do it yourself with C extension PHP (i)
Http://blog.ly5.org/archives/122.html
?
Do it yourself. C extension PHP (ii)-function
Http://blog.ly5.org/archives/123.html
?
Do it yourself with C extension PHP (iii)-IMPORTANT Zend API functions
Http://blog.ly5.org/archives/124.html
?
?
How to write PHP extensions in C
Http://www.ej38.com/showinfo/c-php-212877.html
?