[20241021]使用gdb查看修改内存地址以及相关值.txt

[20241021]使用gdb查看修改内存地址以及相关值.txt

--//执行oradebug poke报错,感觉oracle已经禁止这类hack操作。

1.环境:
SYS@book> @ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0

PL/SQL procedure successfully completed.

2.问题提出:
SYS@book> oradebug setmypid
Statement processed.

SYS@book> @ opeek 00000000649AD2B8 32 1
New tracefile_identifier = /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_4208_0001.trc
Statement processed.
[0649AD2B8, 0649AD2D8) = 00000000 00000000 04C55EAC 0000D2E8 11280D5A 00000000 00000000 00000000

SYS@book>  oradebug poke 0x00000000649AD2B8 8 0x0000012700000127
ORA-32519: insufficient privileges to execute ORADEBUG command: execution of ORADEBUG commands is disabled for this instance

--//很明显oracle禁止这类操作,找到链接https://www.xifenfei.com/2016/07/oradebug-poke-ora-32521-ora-32519.html
--//可惜作者并没有讲如何实现的细节。不过gdb使用应该可以查看修改值,测试看看。

3.测试:
$ cat m1.txt
DECLARE
   v_pad   VARCHAR2 (200);
   l_count PLS_INTEGER;
BEGIN
    FOR i IN 1..&&1
    LOOP
       --EXECUTE IMMEDIATE 'select pad from t where id = :j ' INTO v_pad USING i;
       --EXECUTE IMMEDIATE 'select count(distinct pad) from t where id = :j ' INTO l_count USING i;
       EXECUTE IMMEDIATE 'select count(*) from t where id = :j ' INTO l_count USING i;
           --select count(*) into l_count from t where id = 1 ;
    END LOOP;
END;
/

$ zzdate;seq 10 | xargs -P 10 -IQ sqlplus -s -l scott/book@book01p @m1.txt 1e6 > /dev/null;zzdate
trunc(sysdate)+17/24+01/1440+49/86400 == 2024/10/20 17:01:49 === 2024-10-20 17:01:49== "timestamp'2024-10-20 17:01:49'"
trunc(sysdate)+17/24+02/1440+39/86400 == 2024/10/20 17:02:39 === 2024-10-20 17:02:39== "timestamp'2024-10-20 17:02:39'"

SYS@book> @ mutexprofz id,maddr,loc "ts>=trunc(sysdate)+17/24+01/1440+49/86400 and hash=1607470161"
-- MutexProf by Tanel Poder (http://www.tanelpoder.com)
-- Showing profile of top 20 sleeps...
-- display column info : id hash hash_value=>hash_value ts=>sleep_timestamp req=>requesting_session blk=>blocking_session val=>mutex_value maddr=>mutex_addr

SUM_SLEEPS           GETS MUTEX_TYPE              ID mutex_addr           GET_LOCATION                      OBJECT_NAME
---------- -------------- --------------- ---------- -------------------- --------------------------------- -------------------------------------
        11        1083007 Cursor Pin      1607470161 000000006EBCD060     kksLockDelete [KKSCHLPIN6]        select count(*) from t where id = :j
         5         327504 Cursor Pin      1607470161 000000006EBCD060     kksfbc [KKSCHLFSP2]               select count(*) from t where id = :j

SYS@book> @ opeek 000000006EBCD060 32 0
New tracefile_identifier = /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_5371_0013.trc
Statement processed.
[06EBCD060, 06EBCD080) = 00000000 00000000 02625BD0 00001D6B 5FD00C51 00000000 00000000 00000000

4.使用gdb查看是否可行:
(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
  t(binary), f(float), a(address), i(instruction), c(char) and s(string).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.

Defaults for format and size letters are those previously used.
Default count is 1.  Default address is following last thing printed
with this command or "print".

(gdb) x /8x 0x000000006EBCD060
0x6ebcd060:     0x00000000      0x00000000      0x02625bd0      0x00001d6b
0x6ebcd070:     0x5fd00c51      0x00000000      0x00000000      0x00000000
--//完全能对上oradebug peek的显示。

(gdb) x /4xg 0x000000006EBCD060
0x6ebcd060:     0x0000000000000000      0x00001d6b02625bd0
0x6ebcd070:     0x000000005fd00c51      0x0000000000000000
--//注意g格式显示问题,大小头对调。

5.使用gdb修改呢?
--//再次提醒这类操作小心,不小心可能导致crash以及数据库破坏,千万不要在生产系统做这类操作!!

--//看一些文档:
set *(unsigned char      *)<memaddr> = <value>  ; write 1 byte
set *(unsigned short     *)<memaddr> = <value>  ; write 2 bytes
set *(unsigned int       *)<memaddr> = <value>  ; write 4 bytes
set *(unsigned long long *)<memaddr> = <value>  ; write 8 bytes
or
set *(char      *)<memaddr> = <value>           ; write 1 byte
set *(short     *)<memaddr> = <value>           ; write 2 bytes
set *(int       *)<memaddr> = <value>           ; write 4 bytes
set *(long long *)<memaddr> = <value>           ; write 8 bytes

--//打开会话:
--//session 1:
SCOTT@book01p> @ spid
==============================
SID                           : 270
SERIAL#                       : 47427
PROCESS                       : 5719
SERVER                        : DEDICATED
SPID                          : 5721
PID                           : 66
P_SERIAL#                     : 20
C50                           : alter system kill session '270,47427' immediate;
PL/SQL procedure successfully completed.

--//sid=270 = 0x10e , 填充8位 0000010e。
(gdb) set *(unsigned long long *)0x000000006EBCD060 = 0x0000010e0000010e

(gdb) x /8xw 0x000000006EBCD060
0x6ebcd060:     0x0000010e      0x0000010e      0x02625bd0      0x00001d6b
0x6ebcd070:     0x5fd00c51      0x00000000      0x00000000      0x00000000

--//这样如果sid=270执行m1.txt脚本,会报错出现自锁,因为里面的blk的sid=270。
SCOTT@book01p> @ m1.txt 1
DECLARE
*
ERROR at line 1:
ORA-04024: self-deadlock detected while trying to mutex pin cursor 0x06C892E58
ORA-06512: at line 9

--//看报错信息。看看地址0x06C892E58在哪里?

SYS@book> @ fchaz 0x06C892E58
GET_LOCATION                      KSMCHPTR           KSMCHIDX   KSMCHDUR KSMCHCOM           KSMCHSIZ KSMCHCLS   KSMCHTYP KSMCHPAR         KSMCHPTR_BEGIN   KSMCHPTR_END+1
--------------------------------- ---------------- ---------- ---------- ---------------- ---------- -------- ---------- ---------------- ---------------- -----------------
SGA                               000000006C892E28          1          1 KGLHD                   560 recr             80 00               000000006C892E28 000000006C893058

SYS@book> @ sharepool/shp4 '' 1607470161
HANDLE_TYPE            KGLHDADR         KGLHDPAR         C40                                        KGLHDLMD   KGLHDPMD   KGLHDIVC KGLOBHD0         KGLOBHD6           KGLOBHS0   KGLOBHS6   KGLOBT16   N0_6_16        N20   KGLNAHSH KGLOBT03        KGLOBT09
---------------------- ---------------- ---------------- ---------------------------------------- ---------- ---------- ---------- ---------------- ---------------- ---------- ---------- ---------- --------- ---------- ---------- ------------- ----------
child handle address   000000006C892E58 000000006B8B3430 select count(*) from t where id = :j              0          2          0 000000006BF4FFB8 000000006EBCD108       8128      16176       4214     28518      28518 1607470161 3qa9k69gx032j          0
parent handle address  000000006B8B3430 000000006B8B3430 select count(*) from t where id = :j              0          0          0 000000006CADC3A0 00                     4064          0          0      4064       4064 1607470161 3qa9k69gx032j      65535
--//指向child handle address,KGLHDADR=000000006C892E58。

(gdb) set *(unsigned long long *)0x000000006EBCD060 = 0x000001050000010e
(gdb) x /8xw 0x000000006EBCD060
0x6ebcd060:     0x0000010e      0x00000105      0x02625bd0      0x00001d6b
0x6ebcd070:     0x5fd00c51      0x00000000      0x00000000      0x00000000
--//注意看x的输出,大小头问题,0x00000105在后,0x0000010e在前。
--//如果害怕出错,可以采用4字节修改方式。set *(int       *)<memaddr> = <value>  ; write 4 bytes

--//session 1:
SCOTT@book01p> @ m1.txt 1

--//挂起!!说明第4-7字节表示blk会话。

(gdb) set *(unsigned int       *)0x000000006EBCD064 = 0x00000000
No type named unsigned signed int.
--//嗯,报错!!尝试set *( int       *)修改看看。

(gdb) set *( int       *)0x000000006EBCD064 = 0x00000000
--//注意我输入的地址是0x000000006EBCD064.

--//session 1:
SCOTT@book01p> @ m1.txt 1
PL/SQL procedure successfully completed.

(gdb) x /8xw 0x000000006EBCD060
0x6ebcd060:     0x0000010e      0x00000000      0x02625bd2      0x00006b5b
0x6ebcd070:     0x5fd00c51      0x00000000      0x00000000      0x00000000

(gdb) set *( int       *)0x000000006EBCD060 = 0x00000000
(gdb) x /8xw 0x000000006EBCD060
0x6ebcd060:     0x00000000      0x00000000      0x02625bd2      0x00006b5b
0x6ebcd070:     0x5fd00c51      0x00000000      0x00000000      0x00000000
--//前面4位表示共享模式获取的mutex的数量。