a jéje, za 19 kaček vám povíme IQ, ale my sme si ho už šlohli, tak načo platiť? 😃
majme takýto prípad: zdroj: https://www.zive.cz/clanky/openai-agenti-predali-vzkaz-pres-cache-procesoru/sc-3-a-244081/default.aspx
prepísali rýchle registrové pamäte? zaujímavé, ak mám teda sandboxovaný program, takto z neho vyskočím? čo sigterm na overflow? veď spectre a ghost sú ošetrené? chyba v adresovaní ram spôsobí chybu v adresovaní registra?
tu je výsledok mojich testov: https://hrubos.tech/repository/C_spectre.zip
linux7@linux7:~/C_spectre$ gcc -g -O0 flags.c -o flags
linux7@linux7:~/C_spectre$ gdb ./flags
GNU gdb (Ubuntu 15.1-1ubuntu1~24.04.1) 15.1
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./flags...
(gdb) break main
Breakpoint 1 at 0x1131: file flags.c, line 4.
(gdb) run
Starting program: /home/linux7/C_spectre/flags
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main () at flags.c:4
4 __asm__ volatile (
(gdb) disassemble /r main
Dump of assembler code for function main:
0x0000555555555129 <+0>: f3 0f 1e fa endbr64
0x000055555555512d <+4>: 55 push %rbp
0x000055555555512e <+5>: 48 89 e5 mov %rsp,%rbp
=> 0x0000555555555131 <+8>: b8 00 00 00 00 mov $0x0,%eax
0x0000555555555136 <+13>: 85 c0 test %eax,%eax
0x0000555555555138 <+15>: b8 00 00 00 00 mov $0x0,%eax
0x000055555555513d <+20>: 5d pop %rbp
0x000055555555513e <+21>: c3 ret
End of assembler dump.
(gdb) break *0x555555555136
Breakpoint 2 at 0x555555555136: file flags.c, line 4.
(gdb) continue
Continuing.
Breakpoint 2, 0x0000555555555136 in main () at flags.c:4
4 __asm__ volatile (
(gdb) info registers eflags
eflags 0x246 [ PF ZF IF ]
(gdb) si
12 return 0;
(gdb) info registers eflags
eflags 0x246 [ PF ZF IF ]
(gdb) break *0x555555555131
Note: breakpoint 1 also set at pc 0x555555555131.
Breakpoint 3 at 0x555555555131: file flags.c, line 4.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/linux7/C_spectre/flags
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main () at flags.c:4
4 __asm__ volatile (
(gdb) set $eflags = $eflags & ~0x40
(gdb) break *0x555555555136
Note: breakpoint 2 also set at pc 0x555555555136.
Breakpoint 4 at 0x555555555136: file flags.c, line 4.
(gdb) continue
Continuing.
Breakpoint 2, 0x0000555555555136 in main () at flags.c:4
4 __asm__ volatile (
(gdb) info registers eflags
eflags 0x206 [ PF IF ]
(gdb) si
12 return 0;
(gdb) info registers eflags
eflags 0x246 [ PF ZF IF ]
(gdb)
program main.c:
#include <stdio.h>
int main(void)
{
char retazec[4] = {'A', 'B', 'C', 'D'};
// Chyba: reťazec neobsahuje ukončovací znak '\0'
printf("%s\n", retazec);
return 0;
}
program flags.c:
int main(void)
{
__asm__ volatile (
"mov $0, %%eax\n\t"
"test %%eax, %%eax\n\t"
:
:
: "eax", "cc"
);
return 0;
}
všimnúť si hardwérovú chybu procesora intel:
Breakpoint 2, 0x0000555555555136 in main () at flags.c:4
4 __asm__ volatile (
(gdb) info registers eflags
eflags 0x206 [ PF IF ]
(gdb) si
12 return 0;
(gdb) info registers eflags
eflags 0x246 [ PF ZF IF ]
(gdb)
Vysvetlenie z AI/GPT:
2. Čo sa zmenilo na úrovni bitov?
Príznak ZF zodpovedá bitu 6 registra RFLAGS/EFLAGS, teda maske 0x40.
- Pred inštrukciou: 0x206 — bit 0x40 je nulový.
- Po inštrukcii: 0x246 — bit 0x40 je nastavený.
Rozdiel je presne:
0x246-0x206=0x40
Tým si experimentálne overil, že inštrukcia procesora
zmenila príznak ZF. Príkazom set $eflags = ... si
predtým zámerne vynuloval príslušný bit, aby bola
zmena jasne viditeľná.
3. Ako to súvisí s chybným ukončením reťazca?
Toto je dôležité rozlíšenie:
- ZF je príznak výsledku inštrukcie, nie príznak chyby programu.
- AddressSanitizer zistil, že puts() čítal za hranicou poľa retazec.
- #PF (page fault) je hardvérová výnimka, ktorá môže vzniknúť pri prístupe na neprístupnú stránku pamäte.
ZÁVER TESTU: PF (page fault) je hardvérová výnimka, ktorá môže vzniknúť pri prístupe na neprístupnú stránku pamäte.

https://hrubos.tech/blogy/content/images/20261025165025-hw_vynimka_cpu.jpg
Reading symbols from ./segv_demo...
(gdb) handle SIGSEGV stop print pass
run
Unrecognized or ambiguous flag word: "run".
(gdb) handle SIGSEGV stop print pass
Signal Stop Print Pass to program Description
SIGSEGV Yes Yes Yes Segmentation fault
(gdb) run
Starting program: /home/linux7/C_spectre/segv_demo
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00005555555551c0 in main () at segv_demo.c:17
17 volatile char hodnota = *p; // Zámerná chyba
(gdb) info registers
rax 0x7ffff7fba000 140737353850880
rbx 0x7fffffffdd18 140737488346392
rcx 0x7ffff7d255ec 140737351144940
rdx 0x0 0
rsi 0x1000 4096
rdi 0x0 0
rbp 0x7fffffffdbf0 0x7fffffffdbf0
rsp 0x7fffffffdbd0 0x7fffffffdbd0
r8 0xffffffff 4294967295
r9 0x0 0
r10 0x22 34
r11 0x246 582
r12 0x1 1
r13 0x0 0
r14 0x555555557db8 93824992247224
r15 0x7ffff7ffd000 140737354125312
rip 0x5555555551c0 0x5555555551c0 <main+87>
eflags 0x10213 [ CF AF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
fs_base 0x7ffff7f98740 140737353713472
gs_base 0x0 0
(gdb) x/i $rip
=> 0x5555555551c0 <main+87>: movzbl (%rax),%eax
(gdb) p $_siginfo
$1 = {si_signo = 11, si_errno = 0, si_code = 2, _sifields = {_pad = {-134504448, 32767, 0 <repeats 26 times>}, _kill = {si_pid = -134504448, si_uid = 32767},
_timer = {si_tid = -134504448, si_overrun = 32767, si_sigval = {sival_int = 0, sival_ptr = 0x0}}, _rt = {si_pid = -134504448, si_uid = 32767, si_sigval = {
sival_int = 0, sival_ptr = 0x0}}, _sigchld = {si_pid = -134504448, si_uid = 32767, si_status = 0, si_utime = 0, si_stime = 0}, _sigfault = {
si_addr = 0x7ffff7fba000, _addr_lsb = 0, _addr_bnd = {_lower = 0x0, _upper = 0x0}}, _sigpoll = {si_band = 140737353850880, si_fd = 0}, _sigsys = {
_call_addr = 0x7ffff7fba000, _syscall = 0, _arch = 0}}}
(gdb) x/i $rip
=> 0x5555555551c0 <main+87>: movzbl (%rax),%eax
(gdb) info registers eflags
eflags 0x10213 [ CF AF IF RF ]
(gdb) p $_siginfo
$2 = {si_signo = 11, si_errno = 0, si_code = 2, _sifields = {_pad = {-134504448, 32767, 0 <repeats 26 times>}, _kill = {si_pid = -134504448, si_uid = 32767},
_timer = {si_tid = -134504448, si_overrun = 32767, si_sigval = {sival_int = 0, sival_ptr = 0x0}}, _rt = {si_pid = -134504448, si_uid = 32767, si_sigval = {
sival_int = 0, sival_ptr = 0x0}}, _sigchld = {si_pid = -134504448, si_uid = 32767, si_status = 0, si_utime = 0, si_stime = 0}, _sigfault = {
si_addr = 0x7ffff7fba000, _addr_lsb = 0, _addr_bnd = {_lower = 0x0, _upper = 0x0}}, _sigpoll = {si_band = 140737353850880, si_fd = 0}, _sigsys = {
_call_addr = 0x7ffff7fba000, _syscall = 0, _arch = 0}}}
(gdb)
Takže záver: Nedá sa to, lebo:
Rozdiel oproti dnešnému pokusu je zásadný: - Chýbajúci '\0': program porušuje pravidlá práce s reťazcami v C. Výsledkom je nedefinované správanie; čítanie za hranicou poľa nemusí vyvolať SIGSEGV. - Naša skúška s PROT_NONE: program sa zámerne pokúsil čítať z pamäte, ku ktorej nemá oprávnenie, a preto vznikol SIGSEGV. AddressSanitizer v prvom prípade môže chybu odhaliť vlastnou kontrolou, aj keď samotný procesor pri danom čítaní nevyvolá výnimku.
Najdôležitejší záver: procesor nemá špeciálny bit v EFLAGS, ktorý by znamenal „reťazec nemá '\0'“. Príznaky ako ZF sú niečo iné než hardvérová výnimka pri nepovolenom prístupe do pamäte.
