ELFファイルjumpy
とC言語のソースコードjumpy.c
が与えられ、
Request Session ボタンが用意されていた。
jumpy.c
を読むと、以下のことが読み取れた。
moveax (32ビット符号付き10進整数)
(b8 xx xx xx xx
) : 指定の値をEAXレジスタに格納する。jmp (8ビット符号付き10進整数)
(eb xx
) : プログラムカウンタをこの命令の直後のアドレスに指定の整数を足した値にする。ret
(c3
) : スタックからプログラムカウンタをポップする。jmp
に関しては機械語の構築後にチェックが入り、飛び先の命令がここで挙げたもの以外である場合は実行を拒否する。alarm(5);
を呼び出す。
moveax
命令で設定する値の最下位のバイト(リトルエンディアンで一番最初のバイト)を0xb8に設定し、
jmp
命令でこの最下位のバイトに飛ばすようにすると、
このmoveax
命令の次の命令の最初のバイトまでをmoveax
命令で設定する値と解釈させ、
その次に配置された値を命令として実行させることができる。
すなわち、次のように命令を配置することで、yy yy yy yy
の部分に書いた命令を実行させることができる。
A ELF file jumpy
and a C source code jumpy.c
were given and there was a "Request Session" button.
Reading jumpy.c
, I found these:
moveax (a 32-bit signed decimal integer)
(b8 xx xx xx xx
) : store the specified value to the register EAX.jmp (a 8-bit signed decimal integer)
(eb xx
) : set the program counter to the address right after this instruction plus the specified value.ret
(c3
) : pop the program counter from the stack.jmp
instructions after constructing machine code and refuses to execute that if the instruction at the jump destination is not any of the instructions listed here.alarm(5);
before executing the constructed machine code.
Now think about setting the least byte (the first byte in little-endian) of the value to set in the moveax
instruction to 0xb8
and jumping to the least byte via the jmp
instruction.
This will have it interpret the first byte of the next instruction of this moveax
instruction
and execute the value after that as instructions.
In other words, you can have it execute instructions in the yy yy yy yy
part by placing instructions like this:
また、readelf -h jumpy
の結果は以下のようになり、
実行環境はよくあるx86-64のLinuxであると予想できた。
Also, this is the output of readelf -h jumpy
.
It seemed that the execution environment is the widely-used x86-64 Linux.
ncat --ssl (ドメイン) (整数)
という文字列が表示された。
表示された整数をポート番号と解釈し、
また、手元のOpenSSL (OpenSSL 1.0.2n 7 Dec 2017) を用い、openssl s_client -connect (ドメイン):(ポート番号)
で接続したところ、
証明書やセッションの情報は表示されたものの、すぐに接続が切れてしまった。
以下のサイトから OpenSSL 1.1.1l 24 Aug 2021 をダウンロードし、同様にs_client
で接続すると、通信に成功した。
When I hit the "Request Session" button in
Pressing the button on ncat --ssl (a domain name) (an integer)
appearing after a while.
I assumed that the integer is the port number.
I tried connecting to the domain and the port number via
Also, I tried connection to the server like openssl s_client -connect (domain name):(port number)
with OpenSSL that had already installed (OpenSSL 1.0.2n 7 Dec 2017).
As a result, information about the certificate, the session, etc. was printed, but it became disconnected right after that.
I succeeded to communicate with the server by downloading OpenSSL 1.1.1l 24 Aug 2021 from this page and using s_client
in the same way:
通信ができるようになったので、execve
システムコールを用いて/bin/sh
を実行するコードを送信してみたが、
シェルのコマンドを送信しても反応がみられず、シェルは使えないようだった。
そこで、指定のコマンドを実行させるコードを構築できるようにした。
まず、これが実行させるプログラムのもととなるコードである。
/bin/ls
はexecve
の第2引数が0だと上手く動かないようだったので、
コマンドライン引数の配列も構築するようにした。
Now I found how to communicate with the server.
I tried sending a code to launch /bin/sh
via the execve
system call.
However, no response appeared after sending commands for shell and the shell didn't look available.
After that, I prepared to build a code to execute the specified command.
This is a program for building the code to execute based on.
Testing on /bin/ls
doesn't work well when the 2nd argument of execve
is set to zero.
Therefore, I had this program construct the array for the command-line arguments.
これをもとにして、指定したコマンドを実行するコードを構築する以下のプログラムを作成した。
Based on this, I created this program to construct a code to execute the specified command:
以下が、このプログラムで構築した /bin/ls
を実行するコードである。
This is a code to execute /bin/ls
created via this program:
このコードをサーバに送信すると、ルートディレクトリによくあるディレクトリ名に混ざって flag
という項目が出力された。
そこで、コードを構築するプログラムを改良し、引数を1個指定できるようにした。
以下がその改良後の構築プログラムと、そのもととなるコードである。
Sending this code to the server, I found an entry flag
printed among the common directory names in the root directory.
Seeing this, I updated the program to construct a code to enable it specifying an argument.
These are the updated program and a program to work based on:
これを用いて以下の /bin/cat flag
を実行するコードを構築し、サーバに送信すると、flagが出力された。
I built this code to execute /bin/cat flag
via this program and sent it to the server, finding the flag printed.