[20241021]使用gdb檢視修改記憶體地址以及相關值.txt

lfree發表於2024-10-21
[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的數量。


相關文章