[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的数量。