level1 第一关就被卡了好久:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <stdio.h> #include <unistd.h> void pwncollege (char * argv[],char *env[]) { char *newenv[]={NULL }; execve("/challenge/embryoio_level1" ,newenv,env); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
但其实不用这么写也可以,只是因为我习惯在 vscode 给的 terminal 里运行程序,所以它会主动去穿一些参数。但如果用 VNC 连的桌面开一个 bash 就可以直接运行程序给的题目二进制了。
level2/3/4 直接运行给个参数就行了。4需要给个环境变量再运行
level5 重定向输入:
1 ./embryoio_level5 < /tmp/inujwj
level6 重定向输出:
1 ./embryoio_level6 > /tmp/tzdetd
level7 无环境变量去运行该程序。写一个程序调用 execve 去跑目标程序,不过要编译为 bash:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <stdio.h> #include <unistd.h> void pwncollege (char * argv[],char *env[]) { char *newenv[]={NULL }; execve("/challenge/embryoio_level1" ,newenv,newenv); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level8/9/10/11/12/13 写个脚本然后运行程序即可。
level14 脚本里写:
1 env -i /challenge/embryoio_level14
level22 1 2 import subprocess subprocess.run("/challenge/embryoio_level22" )
level23/24/25/26/27 基本不变
level28 1 2 3 import subprocess subprocess.run(["/challenge/embryoio_level28])
level29 要求用 fork 开子进程然后调用文件,套一下之前的代码:
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 #include <stdio.h> #include <unistd.h> void pwncollege (char * argv[],char *env[]) { char *newenv1[]={'bash' ,"/home/hacker/Desktop/sc.sh" ,NULL }; char *newenv2[]={NULL }; execve("/challenge/embryoio_level29" ,newenv2,newenv2); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level30/31/32/33/34/35 基本套用给上一个脚本
level36 程序和上一个基本一样,但是把输出用管道符传给 cat:
level37
level40 要求重定向 stdin 并通过管道符给程序,并且还要求用 cat。不过 cat 如果有目标文件直接就结束退出了,但是单输入一个 cat 会让程序挂起,然后就可以输入了:
level42/44 基本同上。
level47 有点麻烦,rev 在无参的情况下看起来和 cat 差不多,但是这次却没成功,于是写了个程序命名为 rev 然后去传参:
1 2 3 4 5 6 7 #include <stdio.h> #include <stdlib.h> int main () { printf ("%s\n" ,"cfijsyko" ); sleep(5 ); }
程序结束后会吐出 flag
level54/56/58 用 python 重复上面的操作
level60/61/65 这次又换会用 fork 去启了,操作不变。
level66 要求用 find 去启动程序:
1 find "/challenge/embryoio_level66" -exec {} \;
level68 要求给很多参数,直接复制粘贴强行突破了。
不过好像有更简单的方式:
1 /challenge/embryoio_level68 `printf ' godxqtxpvg%0.s' {1..284}`
level71 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 #include <stdio.h> #include <unistd.h> void pwncollege (char * argv[],char *env[]) { char *newenv1[400 ]={"bash" ,"sc.sh" ,NULL }; char *newenv2[]={"195=zyzycfyyds" ,0 }; execve("/challenge/embryoio_level71" ,argv,newenv2); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; pwncollege(argv,env); fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level72 先进目录,然后用 bash 跑脚本,并重定向即可:
1 /tmp/rdsjif$ bash /home/hacker/Desktop/sc.sh < abjvbe
level73 有点麻烦,最后是这样搞定的:
1 2 cd /tmp/gngyds;exec /challenge/embryoio_level73
level74 1 2 3 4 5 import subprocess ar=["/challenge/embryoio_level74" ]for i in range (200 ): ar.append("xkxnlfngaa" ) subprocess.run(ar)
level77 1 2 3 4 5 6 7 8 import subprocessimport os ar=["/challenge/embryoio_level77" ]for i in range (200 ): ar.append("xhgzegeywm" ) os.environ.clear() os.environ["185" ]="pfqthebkev" subprocess.run(ar)
level79 也是换个目录,不过这次是 python 版本:
1 2 3 4 import subprocessimport os ar=["/challenge/embryoio_level79" ] subprocess.call(ar,cwd="/tmp/wnufru" )
level80 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 #include <stdio.h> #include <unistd.h> #include <stdlib.h> void pwncollege (char * argv[],char *env[]) { char *newenv1[400 ]={"/challenge/embryoio_level80" ,NULL }; for (int i=1 ;i<100 ;i++) { newenv1[i]="oikeqbtrns" ; } char *newenv2[]={0 }; execve("/challenge/embryoio_level80" ,newenv1,newenv2); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level83 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 #include <stdio.h> #include <unistd.h> #include <stdlib.h> void pwncollege (char * argv[],char *env[]) { char *newenv1[400 ]={"/challenge/embryoio_level80" ,NULL }; for (int i=1 ;i<300 ;i++) { newenv1[i]="vfnrjapwqf" ; } char *newenv2[]={"151=mzjtmpkgda" ,0 }; execve("/challenge/embryoio_level83" ,newenv1,newenv2); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level85 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 #include <stdio.h> #include <unistd.h> #include <stdlib.h> void pwncollege (char * argv[],char *env[]) { chdir("/tmp/uejsun" ); execve("/challenge/embryoio_level85" ,argv,env); return ; } int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level86 脚本跑起来之后输入数字即可
level87 不会写脚本,直接手撸了,还好不多
level88/89 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <stdio.h> #include <unistd.h> #include <stdlib.h> void pwncollege (char * argv[],char *env[]) { char *newenv1[400 ]={"/tmp/rciroo" ,NULL }; execve("/challenge/embryoio_level88" ,newenv1,env); return ; }int main (int argc,char * argv[],char * env[]) { pid_t fpid; fpid=fork(); if (fpid<0 ) printf ("error in fork!\n" ); else if (fpid==0 ){ printf ("我是子进程\n" ); pwncollege(argv,env); } else { printf ("我是父进程\n" ); wait(NULL ); } return 0 ; }
level94 先创建一个 fd=70 的描述符,然后读重定向给 stdin:
1 2 3 4 $cat sc2.sh wvrrmdmh$exec 70<sc2.sh$bash sc.sh 0<&70
level97 1 2 bash sc.shkill -SIGUSR2 2346
level99 python 启动后做个计算就行了。
level100 1 2 3 4 5 6 7 8 9 from pwn import * p=process("/challenge/embryoio_level100" )for i in range (5 ): p.recvuntil("CHALLENGE! Please send the solution for: " ) data=p.recv() p.sendline(str (eval (data))) p.interactive()
level102 注意,这里的 sleep 是必须的,因为父进程提前结束会让子进程被根进程接管,导致父进程不是 python,过不去题目的检查:
1 2 3 4 5 6 7 8 9 import osimport time pid = os.fork()if pid > 0 : print ("父进程,子进程的PID:" , pid) time.sleep(5 )else : print ("子进程,父进程的PID:" , os.getppid()) os.execve('/challenge/embryoio_level102' , ['jvuwqe' ], {})
level103 fifo 管道的使用。
1 2 mkfifo testf echo ndvbtdxa > testf
另外开个窗口用 python 去跑程序:
level104/105 104 跟上一题差不多,就是重定向一下输出而已。105 就是把两个都重定向一下
level106 和前面的有点不太一样。先写个 python 去跑程序:
1 2 3 4 5 import subprocess fd1=open ("testf" ,"r" ) fd2=open ("testf2" ,"w" ) p=subprocess.run("/challenge/embryoio_level106" ,stdin=fd1,stdout=fd2)
然后另外开一个终端:
1 2 cat < testf2 & cat > testf
这里不能把重定向去掉,比如另外开两个终端分别去 cat 管道文件:
这会导致阻塞。看起来像是文件,但实际使用还是要用重定向的方式去用。
level107 1 2 3 4 5 6 7 import subprocessimport osimport timefrom pwn import * context.log_level="debug" fd=os.dup2(102 ,102 ) p=subprocess.run("/challenge/embryoio_level107" ,stdin=102 ,pass_fds=[0 ,1 ,2 ,102 ])
level110 正常启动,然后另外调用 kill 杀掉就行了。
level112/113/115/117/118 正常启动就行了,基本上跟之前的操作一样,不过 113 几个算术题另外拿 python 算了一下。
level120 换个新方法:
1 2 3 4 5 void pwncollege (char * argv[],char *env[]) { dup2(0 ,103 ); execve("/challenge/embryoio_level120" ,argv,env); return ; }
level123 跟之前差不多。
level126 要求是脚本执行,但是不会写 bash 所以用通道的方法转给 python 去解决。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 f1=open ("./testf" ,"rb" ) f2=open ("./testf2" ,"wb" )sum =0 for i in range (6 ): f1.readline() for i in range (3000 ): s=f1.readline() if sum >=500 : print (s) print (f1.read()) break index=s.find(b": " ) if index != -1 : sum +=1 t1=s[index+2 :-1 ] t2=eval (t1) print ("%d : %d" %(sum ,t2)) f2.write(b"%d\n" %t2) f2.flush()
level128 500 个信号,偷个懒,把列表抄过来直接跑:
1 2 3 4 5 6 import osimport subprocess sig=['SIGABRT' , 'SIGUSR1' , 'SIGUSR1' , 'SIGUSR2' , 'SIGABRT' , for i in sig: code="kill " +"-" +i[3 :]+" 5590" subprocess.run(code,shell=True )
不过不知道为什么这道题没办法用上一题的 fifo 文件去传输出,有点奇怪
level131 1 2 3 4 5 6 7 from pwn import * p=process("/challenge/embryoio_level131" )for i in range (500 ): p.recvuntil("Please send the solution for: " ) p.sendline(str (eval (p.recv()))) p.interactive()
level133 照搬上面
level136 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fd1=open ("testf" ,"r" ) fd2=open ("testf2" ,"w" )for i in range (6 ): fd1.readline()sum =1 for i in range (3000 ): line=fd1.readline() if sum >500 : print (line) for i in range (5 ): print (fd1.readline()) break if "Please send the solution for: " in line: temp=line.split(": " )[1 ] res=eval (temp) fd2.write(str (res)+"\n" ) fd2.flush() print (str (sum )+":" +str (res)) sum +=1 else : print (line)
level138 套脚本
level140 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 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #define SERVER_IP "0.0.0.0" #define SERVER_PORT 1210 #define BUFFER_SIZE 1024 int main () { int sockfd; struct sockaddr_in server_addr ; char buffer[BUFFER_SIZE]; char ans[BUFFER_SIZE]; sockfd = socket(AF_INET, SOCK_STREAM, 0 ); if (sockfd == -1 ) { perror("socket" ); exit (EXIT_FAILURE); } server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); server_addr.sin_port = htons(SERVER_PORT); if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof (server_addr)) == -1 ) { perror("connect" ); exit (EXIT_FAILURE); } while (1 ) { memset (buffer, 0 , BUFFER_SIZE); if (recv(sockfd, buffer, BUFFER_SIZE, 0 ) == -1 ) { perror("recv" ); exit (EXIT_FAILURE); } if (strlen (buffer)>0 ) { printf ("Received: %s\n" , buffer); if (!memcmp ("[TEST] CHALLENGE! Please send the solution" ,buffer,strlen (("[TEST] CHALLENGE! Please send the solution" )))) { memset (ans, 0 , BUFFER_SIZE); read(0 ,ans,BUFFER_SIZE); if (send(sockfd, ans, strlen (ans), 0 ) == -1 ) { perror("send" ); exit (EXIT_FAILURE); } } } } close(sockfd); return 0 ; }
level141 手撸:
1 2 3 from pwn import * p=remote("0.0.0.0" ,1321 ) p.interactive()
level142 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 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #define SERVER_IP "0.0.0.0" #define SERVER_PORT 1719 #define BUFFER_SIZE 1024 int pwncollege () ;int main () { pwncollege(); }int pwncollege () { int sockfd; struct sockaddr_in server_addr ; char buffer[BUFFER_SIZE]; char ans[BUFFER_SIZE]; sockfd = socket(AF_INET, SOCK_STREAM, 0 ); if (sockfd == -1 ) { perror("socket" ); exit (EXIT_FAILURE); } server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); server_addr.sin_port = htons(SERVER_PORT); if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof (server_addr)) == -1 ) { perror("connect" ); exit (EXIT_FAILURE); } while (1 ) { memset (buffer, 0 , BUFFER_SIZE); if (recv(sockfd, buffer, BUFFER_SIZE, 0 ) == -1 ) { perror("recv" ); exit (EXIT_FAILURE); } if (strlen (buffer)>0 ) { printf ("Received: %s\n" , buffer); if (!memcmp ("[TEST] CHALLENGE! Please send the solution" ,buffer,strlen (("[TEST] CHALLENGE! Please send the solution" )))) { memset (ans, 0 , BUFFER_SIZE); read(0 ,ans,BUFFER_SIZE); if (send(sockfd, ans, strlen (ans), 0 ) == -1 ) { perror("send" ); exit (EXIT_FAILURE); } } } } close(sockfd); return 0 ; }