1
2 1 2 /bin/bash /challenge/embryoio_level2
然后输入它提供的值就好了 or
1 2 bash /challenge/embryoio_level2 <<< pkovncmc
3 1 2 /bin/bash /challenge/embryoio_level3 -(arguments)
4 1 2 3 /bin/bash export KEY="VALUE" /challenge/embryoio_level4
or
1 2 /bin/bash env KEY=VALUE /challenge/embryoio_level4
5 1 2 3 4 5 /bin/bash cd /tmpmkdir /etgyzzvim etgyzz (写入fzgfqswr) /challenge/embryoio_level5 < /tmp/etgyzz
6 1 2 /bin/bash /challenge/embryoio_level6 > /tmp/vrpfrz
然后再从/tmp/vrpfrz文件中复制flag就好了
7 1 2 /bin/bash env -i /challenge/embryoio_level7
8 1 2 3 4 5 6 vim my_script.sh /challenge/embryoio_level8 bash my_script.sh
9 1 2 3 4 5 6 7 8 9 vim my_script.sh /challenge/embryoio_level9 bash my_script.sh kdubhqar
10 1 2 3 4 5 6 vim my_script.sh /challenge/embryoio_level10 bojahpqwxu bash my_script.sh
这里最开始一直在想怎么传KEY:VALUE这类型的参数,后面又重新看了n遍题目反应过来是要argv[num]=value
,然后想到第三题直接/challenge/embryoio_level3 arguments
,于是修改my_script.sh
中的命令就好了 (这里能这么传是因为num=1,详见68 )
11 1 2 3 4 5 6 7 8 export anfzwf=vzsqapifswvim my_script.sh /challenge/embryoio_level11 bash my_script.sh
or
1 2 3 4 5 6 7 vim my_script /challenge/embryoio_level11 env anfzwf=vzsqapifsw bash my_script.sh
12 1 2 3 4 5 6 7 8 9 vim /tmp/yujbjc uphcfwxv vim my_script.sh /challenge/embryoio_level12 bash my_script.sh < /tmp/yujbjc
13 1 2 3 4 5 6 7 8 vim my_script.sh /challenge/embryoio_level13 bash my_script.sh < /tmp/smtqwm cat /tmp/smtqwm
14 1 2 3 4 5 6 vim my_script.sh env -i /challenge/embryoio_level14 bash my_script.sh
22 1 vim interaction_python.py
1 2 3 import subprocesssubprocess.run(["/challenge/embryoio_level22" ])
1 2 python interaction_python.py
这里最开始用的是subprocess.call
,但是会报错为是运行在dash
环境下而不是python
环境,后经查阅尝试使用run
通过了
subprocess lib call
函数在python3.5版本之后在大多数情况下已经被run
函数替代,需要捕捉标准输出和标准错误的时候也应当使用run
代替
23 1 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level23" ])
1 2 python interaction_python.py ulelosql
24 1 vim interaction_python.py
1 import subprocess.run(["/challenge/embryoio_level24" ,"ebyhyvaqeu" ])
1 python interaction_python.py
25 1 2 export hapuuh=zuwaknffapvim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level25" ])
1 python interaction_python.py
or
1 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level25" ])
1 env hapuuh=zuwaknffap python interaction_python.py
26 1 2 3 4 vim /tmp/bpamfl albupjkk vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level26" ])
1 python interaction_python.py < /tmp/bpamfl
or
1 2 3 vim /tmp/bpamfl albupjkk vim interaction_python.py
1 2 3 4 5 6 from pwn import *import ospassword_file_fd = os.open ("/tmp/bpamfl" ,os.O_RDWR) print (f"Opening password file on FD:{password_file_fd} " )p = process("/challenge/embryoio_level26" ,stdin=password_file_fd) p.interaction()
1 python interaction_python.py
27 1 2 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level27" ])
1 2 3 python interaction_python.py > /tmp/dkyeje cat /tmp/dkyeje
28 1 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level28" ])
1 2 env -i python interaction_python.py
29
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 <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level29" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); if (WIFEXITED(status)){ int exit_status = WEXITSTATUS(status); printf ("child process exited with exit status:%d\n" ,exit_status); }else if (WIFSIGNALED(status)){ int terminate_signal = WTERMSIG(status); printf ("child process exited with termination signal:%d\n" ,terminate_signal); } } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 gcc -o interaction_c interaction_c.c ./interaction_c
这里要注意waitpid
的调用,如果不加waitpid
,则有可能父进程在子进程执行之前终止(可能导致子进程成为一个孤儿进程),也有可能子进程在父进程之前执行完毕(可能导致子进程成为一个僵尸进程)错误示例可看80
30
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level29" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 4 gcc -o interaction_c interaction_c.c ./interaction_c wwrqjqbv
31
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level31" ,"jbxnucvjoe" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 4 gcc -o interaction_c interaction_c.c ./interaction_c
32
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level32" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 gcc -o interaction_c interaction_c.c env swzqlt=prjzxvuzmr ./interaction_c
or
1 2 export swzqlt=prjzxvuzmr./interaction
33 1 2 3 4 vim /tmp/hdkihv wknjywzj vim interaction.c
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level33" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 gcc -o interaction_c interaction_c.c ./interaction_c < /tmp/hdkihv
or
1 2 3 4 vim /tmp/hdkihv wknjywzj vim input_challenge.c
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 <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int pwncollege () { FILE *file = fopen("/tmp/hdkihv" ,"r" ); if (file == NULL ) { perror("Failed to open input file" ); exit (1 ); } pid_t pid = fork(); if (pid < 0 ) { perror("Failed to fork" ); exit (1 ); } else if (pid == 0 ) { dup2(fileno(file), STDIN_FILENO); fclose(file); execl("/challenge/embryoio_level33" ,NULL ); perror("Failed to execute command" ); exit (1 ); } else { wait(NULL ); } return 0 ; } int main () { pwncollege(); return 0 ; }
1 2 gcc -o input_challenge input_challenge.c ./input_challenge
请注意这里上面使用的是execv
函数,下面使用的是execl
函数,这两个函数的区别在于参数的传递方式。
conclusion execl
:接受可变数量的参数来指定要执行的程序以及传递给该程序的命令行参数,以NULL
结束。
execv
:接受一个指向参数字符串数组的指针,数组中的每个字符串都是要传递给新程序的命令行参数,以NULL
结束。
34
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level34" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 gcc -o interaction_c interaction.c ./interaction_c > /tmp/ivyyzs cat /tmp/ivyyzs
or
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <fcntl.h> #include <unistd.h> int pwncollege () { int outputFile = open("/tmp/ivyyzs" ,O_WRONLY | O_CREAT | O_TRUNC,0644 ); if (outputFile == -1 ){ perror("open" ); return 1 ; } if (dup2(outputFile,STDOUT_FILENO) == -1 ){ perror("dup2" ); return 1 ; } pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level34" ,NULL }; execv(args[0 ],args); perror("execv" ); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 4 gcc -o output_challenge output_challenge.c ./output_challenge cat /tmp/ivyyzs
35
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level34" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 gcc -o interaction_c interaction_c.c env -i ./interaction_c
36 1 2 /bin/bash /challenge/embryoio_level36 | cat
这里一开始被/dev/stdout
误导了,一直写的是cat /dev/stdout
,后面才反应过来/challenge/embryoio_level
的输出就是stdout
了
37 1 2 /bin/bash /challenge/embryoio_level37 | grep pwn
40 1 2 3 /bin/bash cat | /challenge/embryoio_level40doqaxpmr
42 1 2 3 4 5 6 vim my_script.sh /challenge/embryoio_level42 bash my_script.sh | cat
44 1 2 3 4 5 6 vim my_script.sh /challenge/embryoio_level44 bash my_script.sh | sed -n '1,20p'
47 1 2 3 4 5 6 vim my_script.sh rev | /challenge/embryoio_level47 bash my_script.sh hlwhngrm(给的是mrgnhwlh)
or
1 2 3 4 5 6 vim my_script.sh /challenge/embryoio_level47 rev | rev | bash my_script.sh mrgnhwlh(ctrl+D)-
把rev
命令放到sh里面的时候,注意密码要颠倒一下(因为使用了rev),然后输入完之后要用ctrl+D
,而不是Enter
。
记录一下相关的两道题,但40 可以使用Enter
54 1 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level54" ])
1 2 python interaction_python.py | cat
or
1 vim interaction_python.py
1 2 3 4 5 from pwn import *import osp_cat = process("cat" ) p = process("/challenge/embryoio_level54" ,stdout=p_cat.stdin) p_cat.interactive()
1 python interaction_python.py
56 1 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level56" ])
1 python interaction_python.py | sed -n "1,50p"
58 1 vim interaction_python.py
1 2 import subprocesssubprocess.run(["/challenge/embryoio_level58" ])
1 2 cat | python interaction_python.pyzyfswacr
60
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level60" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 gcc -o interaction_c interaction.c ./interaction_c | cat
61
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level60" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 gcc -o interaction_c interaction.c ./interaction_c | grep pwn
65
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level65" ,NULL }; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 3 4 gcc -o interaction_c interaction.c rev | rev | ./interaction_c bffjthhw
66 1 find /challenge -name "embryoio_level66" -exec {} \;
请注意}
和\
有空格,没有空格的话会报错find: missing argument to ``exec
这个错误
68 1 2 3 4 5 6 7 vim my_script.sh /challenge/embryoio_level68 $(seq 1 130) \ nfotwcprbp bash my_script.sh
71 1 2 3 4 5 6 vim my_script.sh env -i env 196=ueaivmvvui /challenge/embryoio_level71 $(seq 1 302) cptxifnelk bash my_script.sh
72 1 2 3 4 5 6 7 8 9 10 mkdir /tmp/ruykrutouch /tmp/ruykru/yyajdavim my_script.sh cd /tmp/ruykru && /challenge/embryoio_level72 < yyajda bash my_script.sh
这里最开始使用的是|
符号,后面查阅资料后换成&&
区别: |
:管道操作符,从一个命令的输出将数据传递给另一个命令进行处理 &&
:逻辑与操作符,在前一个命令成功执行后(返回退出码为0),才继续执行下一个命令
73
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 <unistd.h> #include <stdio.h> #include <stdlib.h> int main (int args,char *argv[],char *env[]) { pid_t pid; pid = fork(); if (pid<0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level73" ,NULL }; chdir("/tmp/uzjwek" ); execve(args[0 ],argv,env); printf ("I am a child process" ); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; }
1 2 3 gcc demo.c -o bash ./bash
震惊我一整年的题!!!(纯属自己蠢逼一个) 先看题目要求: 这里的要求是shell脚本、工作目录在/tmp/uzjwek
,然后祖父进程和运行挑战所在的进程目录要不一样。一开始是想在shell
脚本中运行使用()
创建子进程,然后切换目录运行什么的,但是一直不能拿到flag
。后面查了一些东西后再查看了checker.py
后:
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 def check_bash (process ): print ("[TEST] Checking to make sure the process is the bash shell. If this is a check for the parent process, then," ) print ("[TEST] most likely, this is what you do by default anyways, but we'll check just in case..." ) check_exe_basename(process, 'bash' ) assert len (process.cmdline()) == 1 , f"The shell process must be running in its default, interactive mode (/bin/bash with no commandline arguments). Your commandline arguments are: {process.cmdline()} " def check_shellscript (process ): print ("[TEST] Checking to make sure the process is a non-interactive shell script." ) assert os.path.basename(process.exe()) in [ 'sh' , 'bash' ], f"Process interpreter must be 'sh' or 'bash'. Yours is: {os.path.basename(process.exe())} " assert len (process.cmdline()) == 2 and process.cmdline()[1 ].endswith(".sh" ), f"The shell process must be executing a shell script that you wrote like this: `bash my_script.sh`" PROCESS_TYPE_CHECKERS = { 'python' : check_python, 'bash' : check_bash, 'shellscript' : check_shellscript, 'ipython' : check_ipython, 'binary' : check_binary, 'netcat' : lambda p: check_exe_basename(p, 'nc' ), 'socat' : lambda p: check_exe_basename(p, 'socat' ), 'echo' : lambda p: check_exe_basename(p, 'echo' ), 'cat' : lambda p: check_exe_basename(p, 'cat' ), 'grep' : lambda p: check_exe_basename(p, 'grep' ), 'sed' : lambda p: check_exe_basename(p, 'sed' ), 'find' : lambda p: check_exe_basename(p, 'find' ), 'rev' : lambda p: check_exe_basename(p, 'rev' ), }
这一段的判断是有点草率的,它只是检测运行的程序名为bash
即可,所以后面实在没办法用C完成了整个程序,这样就能正常的在进程中切换目录然后运行程序使祖父程序和挑战程序的目录不一样,就可以通过测试拿到flag
了。使用env
参数是为了传递环境变量给execve
函数通过检测。
在经过请教discord
的Tipsy
大佬后,得到了符合题目要求的解法。记录如下:
1 2 3 4 5 vim my_script.sh bash -c "cd /tmp/uzjwek && /challenge/embryoio_level73" bash my_script.sh
使用 -c
选项可以将一整个命令字符串作为参数传递给 bash
,而没有使用 -c
选项则将命令作为独立的参数传递给 bash
。 简单来说就是有-c
的时候表示两条命令作为一个整体被传递给bash
执行,&&
是一个控制流操作符,表示在执行前一个命令成功后才执行后一个命令,所以总的来说是在/tmp/usjwek
目录下执行/challenge/embryoio_level73
而无-c
参数则就是两个单独的命令,彼此之间并无相互影响,所以bash "cd /tmp/uzjwek && /challenge/embryoio_level73"
自然无法成功
补 :这里或许还可以参考88 和89 这两道题
74 1 vim interaction_python.py
1 2 3 4 import subprocessargs = ["/challenge/embryoio_level74" ] + ["" ]*28 + ["sjzzclepas" ] subprocess.run(args)
77 1 vim interaction_python.py
1 2 3 import subprocess args = ["/challenge/embryoio_level77" ] + ["" ]*100 + ["mivegfmnto" ] subprocess.run(args)
1 2 env -i env 262=obtersrpps python interaction_python.py
79 1 vim interaction_python.py
1 2 import subprocess subprocess.run(["/challenge/embryoio_level79" ],cwd="/tmp/trlvty" )
1 python interaction_python.py
80
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> void pwncollege () { pid_t pid; char *args[328 ]; args[0 ] = "/challenge/embryoio_level80" ; for (int i=1 ;i < 328 ;i++){ args[i] = "wesyhjkrni" ; } args[328 ] = NULL ; pid = fork(); if (pid == 0 ){ printf ("child process is created\n" ); printf ("args[0] = %s\n" ,args[0 ]); printf ("args[327] = %s\n" ,args[327 ]); execv(args[0 ],args); printf ("program finished\n" ); }else if (pid > 0 ){ wait(1 ); }else { int status; waitpid(pid,&status,0 ); printf ("failed to create child process.\n" ); wait(1 ); } } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 gcc -o pg_inac80 pg_inac80.c ./pg_inac80
这题前前后后估计写了5个小时了(也是道自己蠢逼题) 先看题目要求:
要求其实很简单,就是二进制文件运行加个参数。 主要就是卡在这个参数,一开始是想在C
中有没有什么方法能够指定数组的某个位置写进参数,最后试了半天发现这样做出错,因为0和指定位置之间没有值导致指定位置的值会被作为第一个参数传进去,所以也就不符合要求了。 后面就是标准的指定数组大小,使用循环初始化数组,但是这里最开始我使用的是NULL
去初始化之间的值,但是经过gdb
等调试后和查阅资料后发现execv
这类函数是在遇到NULL
之后就会停止执行了(这也是为什么前面的args
最后都要加NULL
的原因)。然后后面使用过0 1
这种数字也不行,排查后才反应过来我的是字符数组,当然不能使用数字,改成字符之后就通过了。这里还要注意waitpid
的使用,不然有时候会有输出有时候没输出,waitpid
具体见29
conclusion 从这道题目可以看出execv
这类函数的参数位置计算,args[327]
就是execv
执行程序时候的第327个参数,也就是说被执行程序本身是作为第0个参数传入的而不是第1个(应该可以这么理解?),还有就是记得execv
是执行到NULL
就会自动停止。
83
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[329 ]; args[0 ] = "/challenge/embryoio_level83" ; for (int i = 1 ; i < 130 ; i++) { args[i] = "a" ;} args[130 ] = "tvutqvsrlj" ; args[131 ] = NULL ; execv(args[0 ],args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 gcc -o interaction_c interaction_c.c env -i env 336=whxtxwutel ./interaction_c
85
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 #include <unistd.h> #include <stdio.h> #include <stdlib.h> int pwncollege () { pid_t pid; pid = fork(); if (pid<0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"/challenge/embryoio_level85" ,NULL }; chdir("/tmp/ykjdxt" ); execv(args[0 ],args); printf ("I am a child process" ); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; } int main (int argc,char **argv) { pwncollege(); return 0 ; }
1 2 gcc -o interaction_c interaction_c.c ./interaction_c
类同73 ,只不过这次是可以正当使用了 notice:这道题和73题写法不一样,细节上也不一样,可以对比一下
86 一开始是直接输入答案的,但是写到87题的时候感觉出题人的本意不是这样的,于是写了蛮久的87题写出来了,详细记录在87 题,以下只贴出本题的答案
1 2 3 4 vim my_script.sh /challenge/embryoio_level86 vim 86.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import *p = process(["bash" ,"my_script.sh" ]) for i in range (1 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for:" ) print (output.decode("utf-8" )) number = p.recvuntil(b"\n" ).strip() print (number.decode("utf-8" )) result = eval (number) print (result) p.sendline(str (result)) print (p.recvuntil("CORRECT!" ).decode("utf-8" )) print (p.recvall(timeout=1 ).decode("utf-8" ))
87 先贴解题记录
1 2 3 vim my_script.sh /challenge/embryoio_level87 vim 87.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *p = process(["bash" ,"my_script.sh" ]) for i in range (5 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) number = p.recvuntil(b"\n" ).strip() result = eval (number) p.sendline(str (result)) print (p.recvuntil("CORRECT!" ).decode("utf-8" ))print (p.recvall(timeout=1 ).decode("utf-8" ))
写到这道题目最开始惯性思维是按照题目要求用bash
脚本解决,所写的bash
脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #!/bin/bash output=$(/challenge/embryoio_level87) problem=$(echo "$output " | grep "CHALLENGE!" | awk -F": " '{print $2}' ) count=0 while [$count -lt 5];do if [ -z "$problem " ];then break ; fi echo "Solving problem $((count+1) ): $problem ..." result=$(echo "$problem " | bc) echo "Result: $result " output=$(/challenge/embryoio_level87 <<< "$result " ) problem=$(echo "$output " | grep "CHALLENGE!" | awk -F": " '{print $2}' ) ((count++)) done flag=$(echo "output" | grep "pwn.college" ) echo "Flag: $flag "
awk -F": " '{print $2}'
:使用 awk
工具来处理文本。参数 -F": "
表示以冒号和空格作为字段分隔符,这样会将每行分割成多个字段。$2
表示打印第二个字段,也就是在冒号和空格后面的内容,即挑战的具体数学问题。
但是这个脚本并不能正确运行,它在运行之后都需要按下回车才能继续运行,这样会导致发送回去的result
产生错位(到现在也没明白)
后面询问了Tipsy
佬后知道佬是使用python
脚本来运行my_script.sh
来完成本题的,所以我尝试按照这个思路解决本题
按照下面这个视频提供的思路,完成了python
脚本的编写。遇到的问题有:
没有办法从一大段字符串中提取到需要的算术式,后面是使用number = p.recvuntil(b"\n").strip()
解决的。这里需要注意的是p.recvuntil()
是一个阻塞操作,它会等待直到找到匹配的字符串才会继续执行。所以这里number
只能获取output
之后的输出知道\n
换行符。
p.sendline()
最开始是直接将result
传了进去,后面调试后发现p.sendline()
需要的是字符串,所以str(result)
解决了。
p.recvall(timeout=1)
: 从连接 p
中接收所有的数据,直到连接关闭或超时。参数 timeout=1
表示最多等待 1 秒钟。这样就可以看到所有的输出了。本脚本相关视频
88 1 2 3 4 5 ln -s /challenge/embryoio_level88 /tmp/lnumjgexport PATH=.:$PATH echo "/tmp/lnumjg" > my_script.shbash my_script.sh
其实这里只需要知道一个点就是程序运行的argv[0]
这个参数是程序本身所在的路径,而且是绝对路径,以上的操作就可以理解了。题目所给的提示在89
89 这是题目的hints
: 翻译一下就是: argv[0]
从要执行的程序路径分别传递到execve()
系统调用中。这意味着它不必与程序路径相同,您可以实际控制它。这对于不同的执行方法是不同的。例如,在C
中,您只需要传入不同的argv[0]
。Bash
有几种方法可以做到这一点,但其中一种方法是使用符号链接(例如,ln -s
命令)和PATH
环境变量的组合。
1 2 3 4 5 6 7 ln -s /challenge/embryoio_level89 cmwgvrexport PATH=.:$PATH echo "cmwgvr" > my_script.shbash my_script.sh
94 1 2 3 4 5 6 7 8 9 vim my_script.sh echo "adbsmqfp" > /tmp/demo exec 82< /tmp/demo /challenge/embryoio_level94 <&82 bash my_script.sh
这里exec
是将/tmp/demo
中的内容关联到文件描述符82
,这里只能使用文件的形式,不能exec 82< adbsmqfp
这样。
97 1 2 3 4 5 6 7 vim my_script.sh /challenge/embryoio_level97 bash my_script.sh kill -SIGABRT 1081
这里其实就是要求在程序运行的时候向指定的进程号发送信号,使用kill
命令就好了。
99 1 vim interaction_python.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *p = process(["/challenge/embryoio_level99" ]) for i in range (1 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) print (output.decode("utf-8" )) number = p.recvuntil(b"\n" ).strip() print (number.decode("utf-8" )) result = eval (number) p.sendline(str (result)) print (p.recvuntil(b"CORRECT!" .decode("utf-8" ))) print (p.recvall(timeout=1 ).decode("utf-8" ))
1 python3 interaction_python.py
这里和89 里面差不多就好了,就是要注意我一开始使用的是subprocess
,但是这里面并没有recvuntil()
这一类的方法,所以后面使用的是process()
,但感觉理论上使用subprocess
里面的pOpen()
这种也能通过,只是感觉过程比较繁琐,所以没有尝试,可能后面有时间会来补一下。
100 1 vim interaction_python.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *p = process(["/challenge/embryoio_level100" ]) for i in range (5 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) print (output.decode("utf-8" )) number = p.recvuntil(b"\n" ).strip() print (number.decode("utf-8" )) result = eval (number) p.sendline(str (result)) print (p.recvuntil(b"CORRECT!" .decode("utf-8" ))) print (p.recvall(timeout=1 ).decode("utf-8" ))
1 python3 interaction_python.py
102 和89 一样的套路
1 2 3 4 ln -s /challenge/embryoio_level102 rtszrhexport PATH=.:$PATH vim 102.py
1 2 3 4 5 6 7 from pwn import *p = process(["rtszrh" ]) print (p.recvall(timeout=1 ).decode("utf-8" ))
103 先看题目要求: 解释一下就是其实还是和以前的差不多,就是要使用fifo
这个特殊的文件,它的本质就是管道,使用man page
可以查看fifo
,然后在mkfifo in
后再在代码中使用dup2
函数重定向一下输入,再将hardcoded password
输入到in
中就好了
1 2 3 4 5 6 7 from pwn import *pipe_fd = os.open ("/home/hacker/in" , os.O_RDWR) os.dup2(pipe_fd, 0 ) subprocess.run(["/challenge/embryoio_level103" ])
1 2 python3 103.py echo dhfxmaac > in
104 这里和上面差不多,只要知道0
是标准输入,1
是标准输出,2
是标准错误输出就好了。就是因为这里你重定向标准输出到了fifo
中,所以你要事先在另一个终端中cat out
去等待输出,然后执行了需要实现的程序后才能看到输出
1 2 3 4 from pwn import *pipe_fd = os.open ("/home/hacker/out" ,os.O_RDWR) os.dup2(pipd_fd,1 ) subprocess.run(["/challenge/embryoio_level104" ])
105 1 2 3 mkfifo in mkfifo outvim 105.py
1 2 3 4 5 6 from pwn import *pipe_in = os.open ("/home/hacker/in" ,os.O_RDWR) pipe_out = os.open ("/home/hacker/out" ,os.O_RDWR) os.dup2(pipe_in,0 ) os.dup2(pipe_out,1 ) subprocess.run(["/challenge/embryoio_level105" ])
1 2 3 cat outpython3 105.py echo wseecbpr > in
O_RDONLY
:以只读方式打开文件。
O_WRONLY
:以只写方式打开文件。
O_RDWR
:以读写方式打开文件。 以上标志其实是C语言的系统调用open
中使用的选项,用于控制文件的打开模式。
106
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *pipe_in = os.open ("/home/hacker/in" ,os.O_RDWR) pipe_out = os.open ("/home/hacker/out" ,os.O_RDWR) p = process(["/challenge/embryoio_level106" ],stdout=os.dup2(pipe_out,1 ),stdin=os.dup2(pipe_in,0 )) for i in range (1 ): output = os.read(pipe_out, 4096 ) start_idx = output.find("CHALLENGE! Please send the solution for: " ) + len ("CHALLENGE! Please send the solution for: " ) end_idx = output.find("\n" , start_idx) number = output[start_idx:end_idx].strip() print (output) number = re.search(r"CHALLENGE! Please send the solution for: (.+)\n" , output) print (number) result = eval (number) os.write(pipe_in,result)
1 2 3 python3 106.py cat outecho result > in
上面是自己结合前面的题自己写的,但是写完之后感觉是有点蠢的,尤其是提取算术式那部分,感觉还是要使用recvuntil()
这个方法更好。这里并不能像前面那样直接使用p.recvuntil()
这种方法,因为我们是使用了fifo
管道来进行输入输出。后经询问后Tipsy
佬后得到了下面这种解决方法:讲解视频
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *pipein_read = os.open ("in" ,os.O_RDWR) pipein_write = os.open ("in" ,os.O_WRONLY) pipeout_read = os.open ("out" ,os.O_RDWR) pipeout_write = os.open ("out" ,os.O_WRONLY) p_in = process("cat" ,stdout=pipein_write) p = process("/challenge/embryoio_level106" ,stdin=pipein_read,stdout=pipeout_write) p_out = process("cat" ,stdin=pipeout_read) p_out.recvuntil(b"solution for: " ) number=p_out.recvuntil(b"\n" ) p_in.sendline(number) p_out.interactive()
107
1 2 3 4 from pwn import *os.dup2(0 ,324 ) p = process("/challenge/embryoio_level107" ,close_fds=False ) print (p.recvall(timeout=2 ).decode("utf-8" ))
1 python3 107.py <<< dpfuhyem
这个参数就是关闭这个关掉其他文件描述符的参数。
110
1 2 3 4 from pwn import *subprocess.run(["/challenge/embryoio_level110" ])
1 2 python3 110.py kill -SIGHUP PID
112 详见136
113 详见136
115
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 #include <stdio.h> #include <stdlib.h> #include <stddef.h> int pwncollege () { return 0 ; } int main (int args,char *argv[],char *env[]) { pwncollege(); pid_t pid; pid = fork(); if (pid < 0 ){ exit (1 ); }else if (pid == 0 ){ char *args[] = {"tajrwe" , NULL }; execv("/challenge/embryoio_level115" , args); exit (1 ); }else { int status; waitpid(pid,&status,0 ); exit (1 ); } return 0 ; }
这里不需要和上面一样ln -s
这样88 ,在C中可以直接指定argv[0]
的值,本题还尝试分别使用了execv
、execvp
两个函数
116
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 <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {} int main (int *agrc,char *argv[]) { int pid = fork(); if (pid == 0 ){ char *argv[] = { NULL }; char *envp[] = { NULL }; int pipe_in = open("/home/hacker/in" ,O_RDWR); dup2(pipe_out,STDIN_FILENO); execve("/challenge/embryoio_level116" ,argv,envp); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 3 gcc -o 116 116.c ./116 echo "qhrysiws" > in
学会使用dup2
函数就行了
117
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 <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {} int main (int *agrc,char *argv[]) { int pid = fork(); if (pid == 0 ){ char *argv[] = { NULL }; char *envp[] = { NULL }; int pipe_out = open("/home/hacker/out" ,O_RDWR); dup2(pipe_out,STDOUT_FILENO); execve("/challenge/embryoio_level117" ,argv,envp); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 3 gcc -o 117 117.c ./117 cat out
118
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {}int main (int *argc, char *argv[]) { int pid = fork(); if (pid == 0 ){ int pipe_in = open("/home/hacker/in" ,O_RDWR); int pipe_out = open("/home/hacker/out" ,O_RDWR); dup2(pipe_in,STDIN_FILENO); dup2(pipe_out,STDOUT_FILENO); execv("/challenge/embryoio_level118" ,NULL ); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 3 gcc -o 118 118.c cat outecho "cpkzuebb" > in
120
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {}int main (int *argc,char *argv[]) { int pid = fork(); if (pid == 0 ){ int pipe_in = open("/home/hacker/in" ,O_RDWR); char *argv[] = {"/challenge/embryoio_level120" ,NULL }; dup2(pipe_in,56 ); execv(argv[0 ],argv); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 gcc -o 120 120.c echo "ozsyamkq" > in
123
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {}int main (int *argc,char *argv[]) { int pid = fork(); if (pid == 0 ){ char *argv[] = {"/challenge/embryoio_level123" ,NULL }; execv(argv[0 ],argv); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 3 gcc -o 123 123.c ./123 kill -SIGUSR1 3632
126 1 2 3 vim my_script.sh /challenge/embryoio_level126 touch 126.py
1 2 3 4 5 6 7 8 9 10 11 from pwn import *p = process(["bash" ,"my_script.sh" ]) for i in range (500 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) number = p.recvuntil(b"\n" ).strip() result = eval (number) p.sendline(str (result)) print (p.recvuntil("CORRECT!" ).decode("utf-8" ))print (p.recvall(timeout=1 ).decode("utf-8" ))
这个开始运行之后要等一会,因为有500个运算式,所以要一点时间。详细思路见87
128 1 2 3 vim my_script.sh /challenge/embryoio_level128 vim 128.py
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 from pwn import *import reimport signalimport osimport timep = process(["bash" , "my_script.sh" ]) output = p.recvuntil(b"in exactly this order:" ).decode("utf-8" ) pid_match = re.search(r"\(PID ([0-9]+)" , output) text = p.recvuntil(b"]" ).decode("utf-8" ) signals_match = re.findall(r"'(SIG\w+)'" , text) if pid_match and signals_match: pid = int (pid_match.group(1 )) print (pid) signals = signals_match for signal_name in signals: s = getattr (signal, signal_name) print (pid,s) os.kill(pid,s) p.recvuntil(b"Correct!\n" ) print ("finish" ) p.interactive()
这道题卡了蛮久,主要一开始还是和前面一样固化思维使用的p.sendline()
这种方法,后面经jdin
佬提醒改用os.kill()
方法。又遇到了执行不了几次os.kill()
这个程序就会关闭的问题,一开始以为是timeout
的问题,然后改timeout
和加入time.sleep(.1)
等方法,但是依然没有效果,在排查一遍后发现可能是因为recvcall
这个方法,貌似在使用这个方法之后p
会被关掉,所以改用尝试recvuntil
方法,然后就成功了。代码中的getattr
和eval(f'')
都可以将字符串转化为signal
库中的信号。
131
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *p = process(["/challenge/embryoio_level131" ]) for i in range (500 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) print (output.decode("utf-8" )) number = p.recvuntil(b"\n" ).strip() print (number.decode("utf-8" )) result = eval (number) p.sendline(str (result)) print (p.recvall(timeout=1 ).decode("utf-8" ))
133 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 from pwn import *import reimport signalimport osimport timep = process(["/challenge/embryoio_level133" ]) output = p.recvuntil(b"in exactly this order:" ).decode("utf-8" ) pid_match = re.search(r"\(PID ([0-9]+)" , output) text = p.recvuntil(b"]" ).decode("utf-8" ) signals_match = re.findall(r"'(SIG\w+)'" , text) if pid_match and signals_match: pid = int (pid_match.group(1 )) print (pid) signals = signals_match for signal_name in signals: s = getattr (signal, signal_name) print (pid,s) os.kill(pid,s) p.recvuntil(b"Correct!\n" ) print ("finish" ) p.interactive()
这道题和128 基本一样,改一下p
的内容就好了
136
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {}int main (int *argc,char *argv[]) { int pid = fork(); if (pid == 0 ){ char *argv[] = {"/challenge/embryoio_level136" ,NULL }; execv(argv[0 ],argv); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 gcc -o 136 136.c vim 136.py
1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import *p = process(["./136" ]) for i in range (500 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) number = p.recvuntil(b"\n" ).strip() result = eval (number) print (result) p.sendline(str (result)) print (p.recvuntil("CORRECT!" ).decode("utf-8" ))print (p.recvall(timeout=1 ).decode("utf-8" ))
138
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void pwncollege () {}int main (int *argc,char *argv[]) { int pid = fork(); if (pid == 0 ){ char *argv[] = {"/challenge/embryoio_level136" ,NULL }; execv(argv[0 ],argv); }else { waitpid(pid,NULL ,0 ); } return 0 ; }
1 2 gcc -o 138 138.c vim 138.py
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 from pwn import *import reimport signalimport os p = process(["./138" ]) output = p.recvuntil(b"in exactly this order:" ).decode("utf-8" ) pid_match = re.search(r"\(PID ([0-9]+)" , output) text = p.recvuntil(b"]" ).decode("utf-8" ) signals_match = re.findall(r"'(SIG\w+)'" , text) if pid_match and signals_match: pid = int (pid_match.group(1 )) print (pid) signals = signals_match for ind, i in enumerate (signals): s = eval (f'signal.{i} ' ) print (ind, i, s) os.kill(pid, s) p.recvuntil(b"Correct!" ) p.interactive()
这道题目和136 思路是一样的
140 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #!/bin/bash HOST="localhost" PORT=1294 exec 3<>/dev/tcp/${HOST} /${PORT} while IFS= read -r line <&3; do echo "Received: $line " done &while :; do read -p "Enter input: " user_input if [[ -z "$user_input " ]]; then break fi echo "$user_input " >&3 done exec 3<&-
这里用不了nc
命令,所以让gpt自己写了一个socket
连接拿来用,学到了怎么使用bash写一个socket
连接了
141 先贴一张运行图,防止以后自己不记得怎么操作的了
上面这种方法是: 先开一个终端运行/challenge/embryoio_level141
,然后运行python脚本,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *p = remote("localhost" ,1229 ) for i in range (5 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) number = p.recvuntil(b"\n" ).strip() print (number) result = eval (number) print (result) p.sendline(str (result)) print (p.recvuntil("CORRECT!" ).decode("utf-8" ))p.interactive()
使用remote
方法来获取程序指定端口1229
的输出,然后按照以前的计算逻辑编写剩下来的计算就好了。这题难点主要是获取程序的输出,因为它是通过网络输出在1229的端口上的,最开始我想的是通过socket去获取输出,然后提取算术式并发送回结果,但是这样并不好去提取表达式,正则非常难写,而且发送结果那个步骤也很奇怪,尝试了几种方法都不能正确将结果发送回程序中并进行下一步,后翻阅pwntools的官方文档发现有remote方法,于是尝试了一下就写出来了
下面是全部逻辑都在一个脚本中方法: 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 from pwn import *import multiprocessingimport subprocessimport time k = process(["/challenge/embryoio_level141" ]) challenge_process = multiprocessing.Process(target=process, args=("/challenge/embryoio_level141" ,)) k.wait() challenge_process.start() time.sleep(2 ) p = remote("localhost" , 1229 ) for i in range (5 ): output = p.recvuntil(b"CHALLENGE! Please send the solution for: " ) expression = p.recvuntil(b"\n" ).strip().decode() print (expression) result = eval (expression) print (result) p.sendline(str (result)) final_output = p.recv().decode() print (final_output)p.interactive()
这份代码里的三种方法其实思路都差不多,把运行/challenge/embryoio_level141
也写进代码中,但是需要注意不能直接process(["/challenge/embryoio_level141"])
,这样因为后续没有对这个进程进行操作,所以它会直接结束,在后面加interactive()
也不行,因此要以子进程的形式去运行,challenge_process = subprocess.Popen(["/challenge/embryoio_level141"])
这个可以运行也表示了这个挑战并不是和以前一样要求在python中运行/challenge
,而是要在要求的语言中去获取端口中的输出信息并进行处理
142 下面是代码:
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 #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #define PORT 1858 #define SIZE 1024 void pwncollege () { return ; } int ainb (char * a,char * b) { long unsigned int len1=strlen (a); long unsigned int len2=strlen (b); if (len1>len2) return 0 ; int xflag=0 ; for (int i=0 ;i<len2-len1;i++){ if (strncmp (a,b+i,len1)==0 ){ xflag=1 ; break ; } } return xflag; } int main (int argc,char * argv[],char * env[]) { int client_socket = socket(AF_INET, SOCK_STREAM, 0 ); if (client_socket == -1 ) { perror("socket" ); return -1 ; } struct sockaddr_in addr ; memset (&addr, 0 , sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); inet_aton("127.0.0.1" , &(addr.sin_addr)); int addrlen = sizeof (addr); int listen_socket = connect(client_socket, (struct sockaddr *)&addr, addrlen); if (listen_socket == -1 ) { perror("connect" ); return -1 ; } printf ("成功连接到一个服务器\n" ); char buf[SIZE] = {0 }; int ret; while (1 ) { while (1 ){ memset (buf, 0 , SIZE); ret = read(client_socket, buf, SIZE); printf ("ret = %d\n" , ret); if (0 >=ret) break ; printf ("buf = %s" , buf); printf ("\n" ); if (1 ==ainb("Please send the solution for: " ,buf)) { break ; } } printf ("请输入你要输入的:" ); scanf ("%s" , buf); write(client_socket, buf, strlen (buf)); write(client_socket, "\n" , 1 ); } close(listen_socket); return 0 ; }
这里就是用C语言实现了一个socket
连接,然后获取输出,再手动计算结果(因为C语言的计算写起来很复杂)输入给程序,最后运行完成获得flag