gen2linux的blog

不要問我gentoo linux的東西, 玩一玩就忘記了....

星期日, 8月 20, 2006

 

Audit Subsystem Trace心得

written by gen2linux 2006/8/20
自由轉載但請註明出處

What is Audit Subsystem?
Audit subsystem是Linux kernel 2.6新增的功能,此子系統能記錄下將各行程的系統呼叫參數,檔案的操作等,以供事後稽核,SELinux subsystem也依賴Audit subsystem提供AVC。下圖為執行Audit subsystem所記錄下的數個系統呼叫。



What is Not Audit Subsystem?
Audit Subsystem並不是一個像Netfilter的hook機制,我們並不能利用這個Audit subsystem來對各系統呼叫做一些「hook」的動作,我們僅能觀察Audit Subsystem所產生的記錄。

Audit Subsystem Trace
我trace的版本是 2.6.17.8,不同的版本可能會有很大的差別。底下的描述也以系統呼叫稽核(syscall audit)為主,不討論檔案操作稽核,也不討論audit tool/audit lib。

在kernel 2.6.17,Audit subsystem的實作主要有三個檔案,分別是在kernel目錄下的audit.c、auditsc.c、auditfilter.c;其中audit.c是Audit subsystem主要架構,包括了audit logging、utility、kernel thread,和Netlink相關的函式;auditsc.c為對syscall驗證的相關實作;auditfilter.c則是對audit filter rule的解析與維護。

就算是將Audit subsystem編入核心中,也並不是每個行程都會受到Audit subsystem的驗證,因為還要受到audit filter的篩選,使用者可以自定filter rule來決定條件,只有符合條件的行程才會被Audit Subsystem驗證記錄。

在 fork時期Audit subsystem會替task(child process)準備好被驗證所需的相關資料程序—fork()替task填入 Audit subsystem的bookkeeping structure—struct audit_context,此結構記錄了該task的audit狀態,系統呼叫的參數及回傳值,該task的pid/uid等資訊。

in kernel/fork.c
static task_t *copy_process(){ /* copy_process()被 do_fork()呼叫*/

if ((retval = audit_alloc(p)))…
}



在建立struct audit_context前先經過audit filter的rule檢查,若成立才建立,否則立刻return表示當前的task不受Audit Subsystem的驗證。

in kernel/audit.c
int audit_alloc(struct task_struct *tsk){
state = audit_filter_task(tsk); /* 跟據 filter決定是否要audit此task*/
if (!(context = audit_alloc_context(state))) {…

/* 將此 task標示為TIF_SYSCALL_AUDIT,表示此task往後的系統呼叫都受到Audit subsystem的驗證*/
set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
}


現在我們假設有一A process已經利用了auditctl tool設定為要audit的行程,並且A process呼叫了某一個syscall:


in arch/i386/kernel/entry.S:

ENTRY(system_call) //系統呼叫handler進入點
pushl %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
testl $TF_MASK,EFLAGS(%esp)
jz no_singlestep
orl $_TIF_SINGLESTEP,TI_flags(%ebp)

no_singlestep:

//看看此task是否有標記成_TIF_SYSCALL_AUDIT(from thread info. struct)
testw $( ………_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
jnz syscall_trace_entry //有,跳到syscall_track_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys

syscall_call:
call *sys_call_table(,%eax,4) //呼叫 syscall
movl %eax,EAX(%esp) # store the return value

syscall_exit:
cli # make sure we don't miss an interrupt…(skip)
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work //有,跳到syscall_exit_work


syscall_exit_work:
testb $(…_TIF_SYSCALL_AUDIT), %cl
jz work_pending
sti # could let do_syscall_trace() call
# schedule() instead
movl %esp, %eax //eax是do_syscall_trace()第一個參數
movl $1, %edx //edx是do_syscall_trace()第二個參數
call do_syscall_trace //do_syscall_trace()有gcc的regparm(3)修飾字,故
//是以register傳遞參數
jmp resume_userspace



syscall_trace_entry:
movl $-ENOSYS,EAX(%esp)
movl %esp, %eax
xorl %edx,%edx
call do_syscall_trace // 呼叫do_syscall_trace()
cmpl $0, %eax
jne resume_userspace


do_syscall_trace()的第一個參數 pt_regs含有行程呼叫syscall時的參數,entryexit則表示是將進入syscall或是將退出syscall。


in arch/i386/kernel/ptrace.c
__attribute__((regparm(3)))
int do_syscall_trace(struct pt_regs *regs, int entryexit){

if (unlikely(current->audit_context)) {
if (entryexit)
audit_syscall_exit(AUDITSC_RESULT(regs->eax), regs->eax);
}

if (unlikely(current->audit_context) && !entryexit)
audit_syscall_entry(AUDIT_ARCH_I386, regs->orig_eax, regs->ebx, regs->ecx, regs->edx, regs->esi);

}



上述的entry.S與do_syscall_trace(),最主要只是要說明Audit subsystem在呼叫真正的sys_xxx之前,以及呼叫完sys_xxx之後作用,概念上如下圖。



在呼叫sys_xxx之前Audit subsystem的audit_syscall_entry()先呼叫audit filter函式以決定此次的syscall是否該被驗證,若是則替該task的struct audit_context結構完成初始化,以便記錄此次的syscall。之後流程返回真正執行syscall routine,syscall routine會使用來自user space的系統呼叫參數,當成是input或output,且結束前會將retval設定給eax。

syscall routine預結束返回resume_userspaces之前,Audit Subsystem的audit_syscall_exit()會將struct audit_context中的內容以文字方式輸出到audit log中。

所以audit_syscall_entry()跟audit_syscall_exit()是兩個所謂的syscall的hook點,使得Audit subsystem能夠有機會觀察syscall routine的各參數和retval。

audit_syscall_exit()是Audit subsystem將syscall資訊寫入log檔的時機,所以可知觀察audit log紀錄僅能得到「呼叫syscall後的參數」,但是無法看到「呼叫syscall前的參數」。大部份的情況下觀察「呼叫syscall後的參數」是比較有意義的,但是某些時候觀察「呼叫syscall前的參數」是比較有用的,例如execve()。

整個的寫入audit log動作,由audit_syscall_exit()呼叫audit_log_exit()開始,如下圖所示。



整個系統中會有一個audit_skb_queue佇列存放要寫入log檔的資料,所有的process所要輸出的audit log都存放在此處。這個queue的consumer是一個kernel thread—kauditd,負責將此queue中的skb利用netlink函式送到u-space。如果queue中沒有skb的話kauditd就schedule()進入睡眠,如果kauditd被喚醒的話表示有某個audit_log_end()將skb丟進queue中了,kauditd便可以趕快將skb處理掉,並且嘗試wake up所有因queue滿而進入睡眠的行程,因為queue可能即將有空位。這樣的整體架構好處是可以射後不理,將log資料交給另一個執行體(a kernel thread)去做真正的傳輸到u-space的工作。

audit_log_start()會先觀察queue是不是滿了,如果滿了則會將process睡一段時間(schedule_timeout())後自行醒來再次檢查queue是否滿了,直到queue有空位後,audit_log_start()會new出一個ab(audit_buffer)來代表將要寫入log的資料描述子,且每個ab中含有一個skb存放資料,用skb來存放的原因是便可以將其丟入queue中。

audit_log_start()會回傳 ab描述子,往後的audit log相關函式都需持著ab進行log動作,如輸出格式化字串audit_log_format()、輸出十六進位字串audit_log_hex()、輸出目前行程資料audit_log_task(),最後呼叫audit_log_end()。 audit_log_end()會將此ab描述子中的skb丟入queue中,並且叫醒kauditd該處理queue了。

About Netlink
傳統上處在user space的應用程式要跟kernel space雙向傳遞非常態性的資料時有數種管道:/proc、sysctl(2)、sysfs、ioctl(2)以及Netlink,Audit subsystem選擇以Netlink的原因是因為Netlink適合大量的傳輸,由其是Log的產生常常相當龐大。相較於其他的方式,Netlink介面的使用也較為直覺:Application利用傳統的BSD Socket介面接收傳送來自kernel space的資料,而核心則利用Netlink數組函式來接收和傳遞來自user space的資料,稍有不同的是Netlink的函式傳輸是以”skb”為單位,而非BSD Socket中的”資料流”概念。有關Netlink可以參考RFC3549。

星期三, 8月 16, 2006

 

oom_killer

在trace audit的程式碼時, 看到了核心中所謂的 oom_killer機制,該機制就是在系統的 memory快耗盡時, 就將各processes的"oom_score"分數拿出來比較, 誰的分數低 kernel就砍掉誰來謄出 memory, 有趣的東西.

 

DSLite的原罪

為了防止user直接到找到原始位置後用其它agent(IE/flashget...)下載, DSLite這個agent將原始位置(包含SMTP account/password)給編碼了, 為了防止 reverse engineering, DSLite也會關掉Title含有某些關鍵字的視窗, DSLite exe主體本身也編了碼(俗稱加了殼).....

可是 agent之所以為 agent, 就是它用 well known的 protocol來跟 server交談, 且其 server也是一般的 http/pop3/smtp server....整個傳輸的架構如下:
User <---> agent (DSLite) <----> Server

DSLite無所不用其極的防堵User跟它本身洩露, 卻對Server端無能為力..

星期二, 8月 15, 2006

 

我不是Linuxer, 但是Just for Fun

第一次接觸 Linux確切的時間我也忘記是何時了? 只大約記得是在大一(1996)時的電腦教室, 聽到同學嘴巴講出這個名詞:"我用Linux架好網頁伺服器了".
當年的暑假, 買了一本白色的 slackware的書, 於是就開始灌了, 記得當時好像還需要5.5吋磁碟片的樣子, anyway, 照著書本做也不是太難.

灌好之後, 太好了, 下一章就是make kernel. = =

因為還未接觸Linux之前我們系上就有幾台Solaris/SunOS了, 所以對這種指令式的操作環境並不是很陌生, 但我怎麼也沒想到make kernel也是 text based, 每一個選項都要選擇....
好啦, 玩完不知在搞啥鬼的 make kernel之後, 下一章就是 X window了,終於有看起來有趣一點的東西了. 啥? XFree86Config跟make kernel一樣, 要一個一個選? 挖勒... 認了. 因為一直搞不定, 結果就是XFree86Config那個設定的按法按到背起來了: Y Y N N [Enter] [Enter] N N...
好啦, X終於出現了, 打開Netscape/上BBS, 沒中文.... orz
找 font? 搞輸入法? 字糊在一起? 亂七八糟一大堆問題要解決, 那年的暑假結束之後, 很無奈的, 雖然玩的很高興, 我從此活在 prompt mode底下了

這段期間, 我的 Linux就跟學校的 Digital Unix工作站 (SysV的另一分支)交替使用. 而不知在何時 Redhat這名詞如星火繚原一樣, 幾乎讓人覺得Redhat等於Linux.

Redhat 4.0好像是我大二的時候的事了, 之後 Redhat 5.0, 6.0, 6.2, 時光流逝, 我也到大四了, 這幾個版本的 Redhat都相當具有代表性. 當時RPM確實是好用, 不過一些比較不熱門的軟體還多是以 tarball釋出, 跟要自己編比起來, package的dependency問題似乎不是這麼critical. 無論如何, 在當時的話還是很難不跟 tar.gz/Makefile打交道.

Redhat 7系列是 security問題多多的版本, 並不是說以前就少, 而是在當時 security issue已經普遍被重視, 效能有了, 接下來就是講求security了, 所以你出包就是被放大, 被加深印象, 不只是linux hacker特別關照你, script kiddie也特別喜愛你, nmap -O 上出現Linux 7跟出現Solaris/SunOS的意思都是一樣的, 都是等於root.....直到研二(2002)的時後, 我還是用 Redhat 6.2.

畢業出社會工作後, Redhat 8.0 很快的出現, 也很快的消失了, 快到令人懷疑它是不是真的存在過, 幸好有RH9的推出. 若要我說 Redhat推出過最廣為使用的版本的話, 相信很多人會跟我一樣說是 Redhat 6.2 (kernel2.2)與Redhat 9.0(kernel 2.4), 這兩個板本算是 Redhat生涯裡重要的里程碑.

很幸運的, 同時間試窗環境X window的發展有了長足的進展, 安裝不再困難, 組態不再複雜, 畫面不再簡陋, 不過我跟它還是不熟悉, 很簡單的原因, 下班後我只想上上網, 打打 game, 而不想搞一些有的沒有的patch, 就算我現在搞好了, 誰知道下個月出新版了是不是又要搞另外一套?

因為我的 kernel沒有 modules, 所以我用 insmod的次數比 modprobe & depmod還要多,我常想這是一件很奇怪的事, 一個會進出 kernel的人, 但是卻不甚了解 modprobe的機制!?
我承認是 old school, 不過也承認有點被 XGL吸引...

星期六, 8月 12, 2006

 

WIFI Chips & packet injection

  1. Atheros --好卡, 802.11abg全方位,目前配 Atheros晶片的卡以 pci/mini pci居多, pcmcia亦有,usb甚少, 不過近期 Atheros已經推出 for usb的晶片, 應該會慢慢變多才是. 使用的感覺(mini-pci)是相當中規中矩/穩定, 國外可找到某 400mW的 mini pci卡, 使用的也是 Atheros.另外我們買過一張Orinoco Lucent 802.11g 的 PCI卡,把焊在上面的鐵殼拆開才發現裡面躲一張Atheros mini pci小卡...
    Atheros的特點還有一個是晶片支援Atheros Virtual AP(VAP),可以把網卡變成一個虛擬AP, 跟hostap不同是的,VAP是Atheros晶片原生支援的.而Madwifi也已經將VAP功能實作出來了.另一個是packet injection的功能, Madwifi也有支援. 不過前陣子Madwifi好像在大翻修,許多功能都不太正常,包括packet injection...
  2. Broadcom BCM43xx--BCM43xx的driver被"開發"出來是最近的事,所以目前driver還很陽春,只有一些基本(managed,ad-hoc)功能, 我們對它做壓力測試(throughput)時不知何故掛點,更不用談packet injection了,但是相信指日可待.
  3. Intel/Centrino -- 中規中矩的卡,聽說也是可以做 packet injection,不過某些類型的封包會被 firmware丟棄.
  4. Prism 2, 2.5, 3, GT--平民卡的選擇,俗又大碗.眾所皆知的是 wlan-ng driver, 此driver支援pci,pcmcia,usb,本來相當優秀,但後來不知為何似乎就沒有在maintain了. Wlan-ng進monitor mode沒甚麼困難,但是要做 packet injection的話需要非官方patch(google chopchop)
    另一款廣為人知的driver是 hostap,印象中 2.6 kernel 好像也有支援了,pcmcia,pcionly.除了可把網卡變成 master mode(AP mode)之外, 聽說 packet injection也可以很容易做到, 不過我當時沒試出來就是. prim54 的packet injection印象中還不行.整個prism系列好像快沉下去了,目前市面上知名brand很少用prism..
  5. Ralink 雷陵RT2x00--另一個平民卡掘起了, 此卡的目前佔有率還不錯,usb/mini pci都有他的蹤影,重要的是此卡在 rt2x00 driver的扶持下可以做 packet injection, 且目前driver的開發相當積極, 一般使用都還不錯, packet injection也沒有問題.目前要玩一些較進階的功能的話選ralink usb的C/P值是最高的.
  6. Zydas合勤--第二款平民卡, Y拍很多三四百的網卡都是用它當晶片,我本身是沒有用過,但是稍看了一下它的source code, 印象中從它的.h感覺是可以進monitor mode,但無法做packetinjection, 不過主要的是他的source code並沒有完全釋放, 夾了一堆.o檔如果不要求packet injection功能的話, 此卡可能是最平價的消費.


 

P2P AP?



轉載 http://matrix21.myweb.hinet.net


這台 Matrix 硬體方面較吸引我的是4個 usb 2.0,這一般 ap很少有,而且還四個,有了 usb很多事就做了不贅述, mini pci也不錯, 可換WIFI卡,不過不能動到OS/firmware的話, 換卡也沒用,沒法驅動.

天線應該是 5dBi的吧, 不錯(跟這台比的Vigor也是5dBi嗎?)軟體方面應該也是最大賣點, designed for P2P,但是我沒有在 p2p,所以沒甚麼感覺. 另外裡面有session測試,我覺得也不錯, 也可以強調出來.VPN我沒有在用, 不過支援如此多的協定也是不錯 .企業等級比較有可能會用的到

速率評比總體感覺確實讓人耳目一新, 連 Smartbit都搬出來, 感覺確實是有下過功夫,只是會不會太累了一點. NAT的效能逼進Ethernet 100Mbits理論值? 相較之下Vigor好像比較一般.那個 WDS我也有點疑惑, 理論上有 WDS橋接的話 throughput應該會砍對半, 可是怎麼還是可以到23MBits/s?數據會不會太優了?anyway如果效能確實有比對手好的話, 我覺得都是可以強調的, 好的地方就是好.

其實我強烈懷疑這台跟 Asus/Linksys 一樣, 都是 open source solution....

 

WIFI Equipment

我的傢伙
15dBi Omni天線, 19 dBi Yagi天線
Ralink ra2561f mini-pci card on hacked Asus WL-500G
LMR400 6M 低耗損線
200mW WIFI Booster功率放大器
kismet & aircrack-ng site survey and crack tools.

一些WIFI天線


炒菜鍋蓋天線 (從PCZone學來的 ==)






 

syscall track history

其實在 kernel 2.4時代就有 http://syscalltrack.sourceforge.net/ 此等非常優秀的 kernel tool了,可以 hook各個 syscalls,且其強大的地方在於它對大部份 syscall的 pointer to structure都能夠解析並傳遞到 user space,而不僅僅只是傳出個位址.(那位址對其他 APPs來說幾乎沒有意義)例如 struct shm, struct sock_addr等等的. 當年 syscalltrack無法解析 execve()中的 char *argv[]參數,所以我們在這部份也有做了一些 dirty hack(簡單的 copy_from_user處理)另外 syscalltrack也解決了一些較特殊的 syscall的 hook的處理方式,例如 fork(), execve(), exit()等...

另一件故事是, 當時我們採用的 Redhat9.0, 其 kernel把 sys_call_table[]的 EXPORT_SYBMOL給關閉了, 也就是把 syscall table的位址給隱藏了不讓其它 kernel module引用, 此舉可能是為了安全起見,但是 syscalltrack強烈依賴此 symbol來實行 syscall hook的動作, 結果就是另一個 dirty hack的開始, 這個技巧很有趣, 簡單說拿已知的 sys_write&sys_read的位址, 動態的在 kernel stack搜尋, 如果找到的話就是在 sys_call_table裡了.(前提是 sys_write跟 sys_read的位址有被 export出來)http://sourceforge.net/mailarchive/forum.php?thread_id=4116192&forum_id=714

那 syscalltrack跟 strace這等程式有何不同? strace只能 trace同一個process(& his childs), 但 syscalltrack是整個系統性的... syscalltrack還可自定 rule,自定 result output format...

不過不知何因, syscalltrack此 project在 2003年已經停止 maintain了...所以我們就將腦筋動到 kernel 2.6內建支援的 audit subsystem了

先講故事...

 

第一篇


第一篇, 做個記錄, 近期內應會貼出trace linux kernel 2.6中 audit子系統(audit subsystem)的心得. 不過有時候很懶的動, 不知道這一時興起玩blog能持續多久, 畢竟也不再年輕了....

Archives

8月 2006   9月 2006   10月 2006   11月 2006   3月 2007  

This page is powered by Blogger. Isn't yours?