自加密破解--xor


  昨天做一個CTF,遇到了一個自加密的題目,聽師傅們說都是原題了,奈何之前沒怎么做過,於是昨天花了下時間好好看了一下,順便學習下。

  首先由url格式和源碼,容易猜測是文件包含,利用這個讀取到index文件源碼:

<?php
/**
 * Created by PhpStorm.
 * Date: 2015/11/16
 * Time: 1:31
 */
header('content-type:text/html;charset=utf-8');
if(! isset($_GET['jpg']))
    header('Refresh:0;url=./index.php?jpg=hei.jpg');
$file = $_GET['jpg'];
echo '<title>file:'.$file.'</title>';
$file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
$file = str_replace("config","_", $file);
$txt = base64_encode(file_get_contents($file));

echo "<img src='data:image/gif;base64,".$txt."'></img>";

/*
 * Can you find the flag file?
 *
 */

?>

  簡單看下,發現是用_替換了config。做到這里還沒思路,這里突破點是在.idea文件夾,.idea文件夾是很多工具編寫代碼時生成的文件夾,如pytharm、phpstorm等均可以生成,本地新建個項目,就會發現里面的內容,大致如下:

然后發現.idea/workspace.xml文件里可能有敏感信息泄露,訪問得到

然后利用之前的文件讀取,讀取該文件源碼,這里_換成config即可,得到源碼如下:

<?php
/**
 * Created by PhpStorm.
 * Date: 2015/11/16
 * Time: 1:31
 */
error_reporting(E_ALL || ~E_NOTICE);
include('config.php');
function random($length, $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz') {
    $hash = '';
    $max = strlen($chars) - 1;
    for($i = 0; $i < $length; $i++)    {
        $hash .= $chars[mt_rand(0, $max)];
    }
    return $hash;
}

function encrypt($txt,$key){
    for($i=0;$i<strlen($txt);$i++){
        $tmp .= chr(ord($txt[$i])+10);
    }
    $txt = $tmp;
    $rnd=random(4);
    $key=md5($rnd.$key);
    $s=0;
    for($i=0;$i<strlen($txt);$i++){
        if($s == 32) $s = 0;
        $ttmp .= $txt[$i] ^ $key[++$s];
    }
    return base64_encode($rnd.$ttmp);
}
function decrypt($txt,$key){
    $txt=base64_decode($txt);
    $rnd = substr($txt,0,4);
    $txt = substr($txt,4);
    $key=md5($rnd.$key);

    $s=0;
    for($i=0;$i<strlen($txt);$i++){
        if($s == 32) $s = 0;
        $tmp .= $txt[$i]^$key[++$s];
    }
    for($i=0;$i<strlen($tmp);$i++){
        $tmp1 .= chr(ord($tmp[$i])-10);
    }
    return $tmp1;
}
$username = decrypt($_COOKIE['user'],$key);
if ($username == 'system'){
    echo $flag;
}else{
    setcookie('user',encrypt('guest',$key));
    echo "╮(╯▽╰)╭";
}
?>

這里要想獲取flag,就必須要使得$_COOKIE['user']的值解密出來等於system,但我們並不知道加密的$key值,而我們是知道guest的密文的,這里是參考的http://bbs.heetian.com/forum.php?mod=viewthread&tid=28,代碼如下:

function ss($txt,$m){
        for($i=0;$i<strlen($m);$i++){
        $tmp .= chr(ord($m[$i])+10);
    }
        $m=$tmp;
        $tmp='';
    $txt=base64_decode($txt);
    $rnd = substr($txt,0,4);
    $txt = substr($txt,4);
    for($i=0;$i<strlen($txt);$i++){
        $key .= $txt[$i] ^ $m[$i];
    }
    $s='0123456789abcdef';
    $txt1='system';
        for($i=0;$i<strlen($txt1);$i++){
        $tmp .= chr(ord($txt1[$i])+10);
    }
        $txt1=$tmp;
        $tmp='';
    for($i=0;$i<16;$i++){
        $tmp = $key.$s[$i];
        for($ii=0;$ii<strlen($txt1);$ii++){
            $txt2 .= $txt1[$ii] ^ $tmp[$ii];
        }
        file_put_contents('1.txt',base64_encode($rnd.$txt2)."\r\n",FILE_APPEND);   
        $txt2='';
        
    }
}
ss('eldUVRdOWRhI','guest'); // 設置獲取的guest用戶的cookie值。

我們先簡單看看代碼:

加密函數:首先是對明文每個字符ascii加10,然后獲取一個4位隨機字符串,然后利用該字符串和$key生成下面要進行異或的MD5值,這里異或次數是和加密明文的長度相關的,然后返回base64加密字符串。

解密函數:首先base64解密,然后截取出4位隨機字符串,$key生成算法一樣,然后同樣根據密文長度進行異或,然后對結果字符串每個字符減10.

這里我們首先要知道的是,xor運算,這是可逆的,測試效果如下:

可以看到,只有在密文和密鑰異或時得到結果少一位,這是因為密鑰和明文長度不一致,php在異或時會自動轉換成相同長度,如下:

回到這個題,他根據長度進行異或,由於根據guest獲取的key進行異或出來的只有5位,知道他是和MD5值異或的,解密時的rnd又是和加密一樣的,因此生成的md5也是一樣的,加上system是6位,所以再暴力猜測一遍第6位的值,即可得到解密后為system的密文。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM