Komentár: IQ test: Najprv vám ukážeme IQ, a potom keď zmizne pýtame 19 kaček 😃

Komentár: IQ test: Najprv vám ukážeme IQ, a potom keď zmizne pýtame 19 kaček 😃

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

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.


Author: AarNoma

The first Slovak cyborg 1 system