Stage 1 clear!
Firstly, there has argv. It sames like that behind.
such as /bin/ls -l: left one represent argv[0], right one represent argv[1], …etc. argc represent the length of argv list.
So in order to satisfy strcmp(argv['A'],"\x00") != 0, I can set argv['A'] = "\x00", and next condition.
1  | argv = ['./input']  | 
Stage 2 clear!
stdio: standard input/output
It uses the read.
- read - read from a file descriptor
 - include: unistd.h
 ssize_t read(int fd, void *buf, size_t count);
| 整数值 | 名称 | unistd.h符号常量 | stdio.h文件流 | 
|---|---|---|---|
| 0 | Standard input | STDIN_FILENO | stdin | 
| 1 | Standard output | STDOUT_FILENO | stdout | 
| 2 | Standard error | STDERR_FILENO | stderr | 
read(0, buf, 4);: read 4 bytes from stdinread(2, buf, 4);: read 2 bytes from stderr
We can easily use pwntools to start our play. This tool we need called process.
1  | process() - Spawns a new process, and wraps it with a tube for communication.  | 
We can create program.
1  | from pwn import process  | 
Cation! stderr_we_want="\x00\x0a\x02\xff" can’t work well. stderr is a file descriptor. open return file descriptor, we can hand it.
Stage 3 clear!
also use process.
Stage 4 clear!
It open a file named \x0a that mean newline in program, but don’t care it. Start to write in file like Stage 2.
fread
size_t fread(void *__restrict__ __ptr, size_t __size, size_t __n, FILE *__restrict__ __stream)- Read chunks of generic data from STREAM.
 - return: This number equals the number of bytes transferred only when size is 1. If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).
 
memcpy
int memcmp(const void *__s1, const void *__s2, size_t __n)- Compare N bytes of S1 and S2.
 
Stage 5 clear!
create a new endpoint for communication, usually 127.0.0.1 as host, 9999 as port(out can link).
use remote in pwntools.
- AF_INET: IPv4 Internet protocols, remote support both IPv4 and IPv6.
 - INADDR_ANY: 
\#define INADDR_ANY ((in_addr_t) 0x00000000), we can use any address we want. htons( atoi(argv['C']) ): depend on we set value onargv['C']bind- bind a name to a socket
 int bind(int __fd, const struct sockaddr *__addr, socklen_t __len)- Traditionally, this operation is called “assigning a name to a socket”.
 
code:
1  | #!/usr/bin/env python  | 
OMG! one write the exp in /tmp/pwn,admin’s soltion
exp
1  | #!/usr/bin/env/ python  | 
os.pipe: create a pipe,return (rear, write), left one is “read out”, right one is “write in”.