pwnable共謀:ライトアップ
これはデバッグを実行し、Cコード(私は本当に知っていない)を読んで良いです楽しい挑戦.
共謀はあなたのコード化されたパスワードより同じ署名を持っているメッセージを与えています.あなたのパスワードがハッシュ関数Xでデータベースでコード化された方法で保存されるように、あなたがサービスにログインするとき、あなたはあなたのパスワードをXにハッシュして、データベースでチェックされます.あなたが直接Xに等しいハッシュYを与えるならば、あなたはパスワードを見つけることなくログインすることができました.例えば、MD 5はそれに弱いです(他の暗号も).これはハッシュの計算の制限によるものだと思います.
メインコードは以下の通りです.
その後、ループは、ベクトルを反復し、
その後、
コマンドラインコール に対して厳密に1つの引数があるかどうかを調べます.引数は20バイト長 でなければなりません与えられたパスワードが
ここから何をしますか.
ループは5回経過し、結果を返します.つまり、関数を与えるものは、5倍に追加されます.
2つの小数点のセクションはリトルエンディアンと32ビットアーキテクチャになります.
なぜ全体の計算だけでなく、結果?なぜなら、20バイトのペイロードが必要だからです.我々は、命令だけでなく、結果を通過している.方法の詳細は、なぜ私に少し不明瞭です.私は2、3の試みをしました、そして、これは結局は働きました.
共謀はあなたのコード化されたパスワードより同じ署名を持っているメッセージを与えています.あなたのパスワードがハッシュ関数Xでデータベースでコード化された方法で保存されるように、あなたがサービスにログインするとき、あなたはあなたのパスワードをXにハッシュして、データベースでチェックされます.あなたが直接Xに等しいハッシュYを与えるならば、あなたはパスワードを見つけることなくログインすることができました.例えば、MD 5はそれに弱いです(他の暗号も).これはハッシュの計算の制限によるものだと思います.
メインコードは以下の通りです.
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
printf(res);
}
return res;
}
int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
ここから面白いセクションが2つあります.unsigned long hashcode = 0x21DD09EC;
このセクションはグローバル変数hashcodeを定義します.後でそれに取り戻そう.unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
printf(res);
}
return res;
}
この関数は文字(すなわち文字列)を取得し、それをベクトル(すなわち配列)にキャストします.それはint* ip = (int*)p;
のセクションです.それはここでの仕事に非常に中心的なので、間違いなくread more必要があります.その後、ループは、ベクトルを反復し、
ip
のすべての値を取得し、結果を返すに合計します.その後、
main()
は機能します:int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
3段階で説明します.hashcode
に等しいならば、我々は挑戦をpwnedしました.ここから何をしますか.
0x21DD09EC
は、我々の最初の手掛かりです.私たちはそれで多くのことをすることができません、これを小数点(それは後で意味をなします)で変えましょう.Python 3.9.1 (default, Dec 13 2020, 11:55:53) [GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x21DD09EC
568134124
>>>
その後、check_password
は我々の第2ステップです.ループは5回経過し、結果を返します.つまり、関数を与えるものは、5倍に追加されます.
568134124 = 5x
Then:568134124 / 5 = x
でも!>>> 568134124 / 5
113626824.8
ここでは浮動小数点ではなく整数で動作する必要があります.次に、剰余や関数を入力する式を変更しましょう.568134124 = 4x + x'
(おそらくそれをするためのより多くのまじめな方法があります、コメントで私に知らせてください、私はかなり前に学校を去りました)>>> 568134124 // 5
113626824
Then:568134124 = 4 * 113626824 + x'
568134124 - (4 * 113626824) = x'
113626828 = x'
テストする>>> 568134124 == (4 * 113626824) + 113626828
True
良い.悪用を書きましょう.そのために、pwntoolsを使います.2つの小数点のセクションはリトルエンディアンと32ビットアーキテクチャになります.
p32(113626824, endian='little')
# and
p32(113626828, endian='little')
以下はexploitです.from pwn import *
payload = p32(113626824, endian='little') * 4 + p32(113626828, endian='little')
p = process(['./col', payload])
ret = p.recvline()
print(ret)
なぜプロセスへの呼び出し前にペイロード?ペイロードをコマンドライン引数として渡す必要があるからです.なぜ全体の計算だけでなく、結果?なぜなら、20バイトのペイロードが必要だからです.我々は、命令だけでなく、結果を通過している.方法の詳細は、なぜ私に少し不明瞭です.私は2、3の試みをしました、そして、これは結局は働きました.
~/.../pwnable.kr/2 >>> python boum.py
[+] Starting local process './col': pid 99792
b'/bin/cat: flag: No such file or directory\n'
そして、それはpwnedです!あなたがそれを楽しんだ希望!Reference
この問題について(pwnable共謀:ライトアップ), 我々は、より多くの情報をここで見つけました https://dev.to/evilcel3ri/pwnable-kr-collusion-write-up-2johテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol