Seems the file keeps adding 0x0D to my saved binary files no matter what setting I put in the fopen
mode
flag.
It's not only affecting fopen
/fwrite
.. but also file_put_contents
.
file_get_contents
I thought was the problem to begin with.. but it turns out this one is actually working okay.. because when I dumped the file using bin2hex() it came out good.
I was blaming at first the std::string
in C++ for this bug.. but it turns out it doesn't even have anything to do with C++ but it's in fact a bug with PHP or maybe with only CentOS linux and I have yet to find a solution to store my file in binary.. best I could do is hexstring dump file which works..
Look at my code and screenshots.
$target_file = "/privatefiles/" . basename($_FILES["a"]["name"]);
$fileTypeExtension = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
//Check file extension.
if($fileTypeExtension != "dll" && $fileTypeExtension != "exe" ) die("ER");
// Check file size
if ($_FILES["a"]["size"] > 10*(1024*1024)) //10 MB cap
die("ER");
//To decode a base64 encoded file (this was a quickfix to fix binary file encoding in C++ part).
$fileContent = file_get_contents($_FILES['a']['tmp_name']);
$fileContent = base64_decode($fileContent);
//fail
$fh = fopen("wtf1.bin", "wb");
fwrite($fh, $fileContent, strlen($fileContent));
fclose($fh);
//fail (exact result as top)
$fh = fopen("wtf2.bin", "wb");
$fileContent = bin2hex($fileContent);
for($i=0;$i<strlen($fileContent);$i+=2)
fwrite($fh, chr(hexdec(substr($fileContent,$i,2))));
fclose($fh);
//good result.. but not binary
$fh = fopen("wtf3.bin", "w");
$fileContent = bin2hex(base64_decode(file_get_contents($_FILES['a']['tmp_name'])));
fwrite($fh, $fileContent);
fclose($fh);
//good result but not binary
file_put_contents($target_file, $fileContent); //good bin2hex.
//fail same as the top 2 fail's.
file_put_contents($target_file."_", file_get_contents($_FILES['a']['tmp_name'])); //bad same as wtf1.bin or wtf2.bin
Here are my screenshots (proof of what is happening from running the code above), and initiating a file upload using C++ application (which cannot be bugged because at first I sent using raw binary mode.. then after this 0x0D 0x0A bug I changed it to base64 encoding to fix the transfer problem.. and it turns out that wasn't even the problem, but in fact a PHP problem I believe..
Here is the original binary file (not altered) this is what I upload (as you can see I stop at 0x0A 0x40 to show you the bug).
Here is wtf1.bin (Just a simple 1 liner of base64_decode to file) at same offset.
Here is wtf2.bin (Some hackery I tried to do to fix this problem using bin2hex which dumps it good) at same offset.
Here is wtf3.bin (bin2hex) which works good at same offset. (0x846 / 2 = 0x423) (same offset confirmed!)
Even this simple upload script, uploads corrupted files with 0xA,0xD
<!DOCTYPE html>
<html>
<head>
<title>Upload your files</title>
</head>
<body>
<form enctype="multipart/form-data" action="test.php" method="POST">
<p>Upload your file</p>
<input type="file" name="uploaded_file"></input><br />
<input type="submit" value="Upload"></input>
</form>
</body>
</html>
<?php
if(!empty($_FILES['uploaded_file']))
{
$path = basename( $_FILES['uploaded_file']['name']);
print_r($_FILES);
$size = filesize($_FILES['uploaded_file']['tmp_name']);
echo "<br>size uploaded = " . $size . "<br>";
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $path)) {
echo "The file ". basename( $_FILES['uploaded_file']['name']).
" has been uploaded<br>";
echo "path = " . $path . "<br>";
echo "size stored = " . filesize($path);
} else{
echo "There was an error uploading the file, please try again!";
}
}
?>
Bug happens when I just upload these bytes in binary format
BC 09 00 00 83 C4 04 BA E8 57 40 00 8D 64 24 00 8A 08 88 0A 40 42 84 C9
I get back on server
BC 09 00 00 83 C4 04 BA E8 57 40 00 8D 64 24 00 8A 08 88 0D 0A 40 42 84 C9
Thanks CBroe and IVO GELOV, The issue was in my FTP/SFTP Client WinSCP. I attached a screenshot which setting you need to turn off so this problem doesn't happen.