Test PHP Carve for JPG files
<p>I am just making a little PHP program/page for fun. My ultimate aim is to allow myself to upload an image file to my, mysql database. Then call that file into a string in ASCII, then carve that file for a JPG file I created.</p>

<p>To test this I used the program FTK Imager along with my web server and the results were less than disireable. Granted I am fairly new to PHP so I know there is probably many things I am ignorant to that I am doing wrong. So I was hoping to get some pointers :)</p>

<p>My procedure - Create and UNCOMPRESSED ad1 image file using FTK Imager. I created an image of a directory that contained multiple files. .docx, .pdf, .jpeg, etc etc. I then added this image file to my webservers directory along with my test page. I then called the page through by browser window.</p>

<p>I was greeted by a single 6. That was my output, a 6. I tried echo'ing some error along the way as the code is executed coupled with some error reporting and the best I can tell, $soff isn't getting the intended value for one reason or another (no value to be exact.)</p>

<p>Why wouldn't this be getting a correct value? I know for a fact these are the correct ASCII Header/Trailer signatures.</p>

<p>Here's my script with the echo'ing and error portions included.</p>

<pre><code>&lt;?php
ini_set('display_errors',1); 
error_reporting(E_ALL);
// Search Criterium
$jpgs = "ÿØÿà";
echo "yoya Start&lt;br /&gt;" . $jpgs;
$jpgeoff = "702";
echo "&lt;br /&gt;" . $jpgeoff;
$jpge = "ÿÙ";
echo "&lt;br /&gt;" . $jpge;
// Input file to string
$ipfile = file_get_contents('testimage.ad1');
// Input file length for math
$m1 = strlen($ipfile);
echo "&lt;br /&gt;" . $m1;
// Check for empty file
if(isset($ipfile)) { } else { echo "ERROR - Empty File!&lt;br /&gt;"; }
// Set starting offset with first criterium find
$soff = strpos($ipfile, $jpgs);
echo "&lt;br /&gt;" . $soff;
// Do math to find where to start substr to cut first part off beginning of string.
$x1 = ($soff - 1);
echo "&lt;br /&gt;" . $x1;
$x2 = ($m1 - $soff);
echo "&lt;br /&gt;" . $x2;
// Execute the final math into cuts.
$ipfile = substr($ipfile, $x1, $x2);
// New input file length for more math.
$m2 = strlen($ipfile);
echo "&lt;br /&gt;" . $m2;
// Set ending offset with jpgeoff to skip false positives for jpegs, then jpge to find real trailer character.
$eoff = strpos($ipfile, $jpge, $jpgeoff);
echo "&lt;br /&gt;" . $eoff;
// Do math to find where to start substr to cut second part off end of string. Start at 0 for beginning of jpg, keep chars via math, cuts rest off.
$y1 = "0";
echo "&lt;br /&gt;" . $y1;
$y2 = ($eoff + 1);
echo "&lt;br /&gt;" . $y2;
// Execute the final math into cuts.
$ipfile = substr($ipfile, $y1, $y2);
// The $ipfile string should now contain the ASCII string of only the JPG file.
echo $ipfile;
?&gt;
</code></pre>

<p>Here's the output in my web browser.</p>

<pre><code>yoya Start
ÿØÿà
702
ÿÙ
16542148

-1
16542148
1
Warning: strpos() [function.strpos]: Offset not contained in string in /var/www/html/test1.php on line 32


0
16
</code></pre>

<p>I referenced my file signature information from here <a href="http://www.garykessler.net/library/file_sigs.html" rel="nofollow">http://www.garykessler.net/library/file_sigs.html</a> , and verified this by viewing my jpg files in FTK Imager.</p>

<p>Best I can figure is that there is a different way I should be telling my script to find the offsets of header/signature information in my image.</p>

<p>Any information is very welcome! This is just for fun and learning.</p>

<p>Thank you :)</p>

<p>EDIT - 7/22</p>

<p>I have been working on my code off and on. I did some editing to better reflect the structure of a JPEG file when it is viewed in hex, which is what I will search in. I am running into one error, it seems that strpos does not "see" 0's? My program is returning nearly spot on results, the headers and everything look great, but strpos or something.... is finding a false positive at these spots in the hex of a jpeg file...</p>

<p><img src="http://i.stack.imgur.com/g10o3.png" alt="False Positive"></p>

<p>It is reading the FFD9 on each side of those two zeros, when I need FFD9 right next to eachother...</p>

<p>Here is my updated code,</p>

<pre><code>&lt;?php
ini_set('display_errors',1); 
error_reporting(E_ALL);
// HEX/STR Functions for converting string to hex and vice versa
function strhex($string)
{
    $hex='';
    for ($i=0; $i &lt; strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}

function hexstr($hex)
{
    $string='';
    for ($i=0; $i &lt; strlen($hex)-1; $i+=2)
    {
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}
// Search Criterium
$jpgs = "ffd8ff";
echo "yoya Start&lt;br /&gt;" . $jpgs;
echo "&lt;br /&gt;jpgoff " . $jpgeoff;
$jpge = "ffd9";
echo "&lt;br /&gt;jpge " . $jpge;
// Input file to string
$ipfileg = file_get_contents('ti.ad1');
// Turn to hex
$ipfile = strhex($ipfileg);
// Input file length for math
$m1 = strlen($ipfile);
echo "&lt;br /&gt;m1 " . $m1;
// Check for empty file
if(isset($ipfile)) { } else { echo "ERROR - Empty File!&lt;br /&gt;"; }
// Set starting offset with first criterium find
$soff = strpos($ipfile, $jpgs);
echo "&lt;br /&gt;soff " . $soff;
// Do math to find where to start substr to cut first part off beginning of string.
$x1 = $soff;
echo "&lt;br /&gt;x1 " . $x1;
$x2 = ($m1 - $soff);
echo "&lt;br /&gt;x2 " . $x2;
// Execute the final math into cuts.
$ipfile = substr($ipfile, $x1, $x2);
// New input file length for more math.
$m2 = strlen($ipfile);
echo "&lt;br /&gt;m2 " . $m2;
// Set ending offset. My jpeg test files had three hits for FFD9, so I need to skip two.
$eoff1 = strpos($ipfile, $jpge);
$eoff2 = ($eoff1 + 1);
$eoff3 = strpos($ipfile, $jpge, $eoff2);
$eoff4 = ($eoff3 + 1);
$eoff = strpos($ipfile, $jpge, $eoff4);
echo "&lt;br /&gt;eoff " . $eoff;
// Do math to find where to start substr to cut second part off end of string. Start at 0 for beginning of jpg, keep chars via math, cuts rest off.
$y1 = "0";
echo "&lt;br /&gt;y1 " . $y1;
$y2 = ($eoff + 4);
echo "&lt;br /&gt;y2 " . $y2;
// Execute the final math into cuts.
$ipfile = substr($ipfile, $y1, $y2);
// Convert hex to ASCII string.
$ipfile = hexstr($ipfile);
// The $ipfile string should now contain the ASCII string of only the JPG file.
echo "&lt;br /&gt;final " . $ipfile;
// Create JPG file.
file_put_contents("test.jpg", $ipfile);
?&gt;
</code></pre>
