2011年9月29日

悠遊卡改卡 當事人已不是駭客

最近悠遊卡被人破解加值的新聞(中時電子報自由時報聯合新聞網TVBS),各報標題均以「駭客」稱當事人,當事人似乎也以駭客自居。但對我來說,他已失去駭客的資格,成為了不折不扣的 Cracker。

駭客(Hacker)和 Cracker 的差別,就像星際大戰裡 Master Yoda 和 Darth Vader 的差別。



(照片取材自 Wikipedia 的 YodaDarth Vader 條目)


Yoda 熟悉絕地武士的絕學戰技,還具有洞察世事的透視力、悲天憫人的胸懷、和指點後人的熱忱,在他身上只感受得到正向的能量。

Darth Vader 本來是絕地武士 Anakin Skywalker,一樣熟悉絕地武士的絕學戰技,可是跨不過失去母親和摯愛的個人仇恨,墜入了黑暗界(the dark side),從此成為殺人無數的魔頭。

Hacker 和 Cracker 在技術能力上的差異也許不太大,但在心態上有極大的距離。Hacker 喜愛了解事物工作的原理和想出巧妙的新用途、並且樂於分享,如果在研究某個系統的運作後找到漏洞,不會用來損人或利己,而是通知事主補洞和/或發表。Cracker 主要目標在入侵,未必有打破沙鍋問到底的研究精神,漏洞不必是自己找到的,拿別人做好的入侵工具也可以,只要能入侵就好,而且入侵通常是為了損人或利己。

悠遊卡公司所使用的 Mifare 系統,過去幾年來已經有學界和開放原始碼界的駭客找出更改卡片上餘額的方法,也都發表了(如 Wired magazine 的報導),用 Google scholar 搜尋 "Mifare",第一頁 就好幾篇破解的研究論文。這次的當事人,拿了他人發表的技術文章,自己實做一遍,成功更改悠遊卡餘額,到此為止都還可以算是駭客在實驗室中的研究、練功行為。如果他找到不同的破解方法、發表出來,一定會受到駭客圈的高度肯定。把改變過的悠遊卡拿去捷運站讀餘額,也可以解釋為驗證破解是否成功。但是把增加餘額的悠遊卡拿去消費好幾次,不論金額是大是小,就是損了人利了己,就是越線了,就是 Cracker!

最後引用 "The Jargon File, version 4.4.8" 中的 Hacker 定義第一條作結。

Hacker:
1. A person who enjoys exploring the details of programmable systems and how to stretch their capabilities, as opposed to most users, who prefer to learn only the minimum necessary. RFC1392, the Internet Users' Glossary, usefully amplifies this as: A person who delights in having an intimate understanding of the internal workings of a system, computers and computer networks in particular.

駭客:
1. 享受探索系統細節和延伸系統能力的人,和大多數只想學會夠用功能的人相反。網際網路使用者名詞彙編(RFC1392)更進一步解釋:「因了解系統內部運作方式而喜悅的人,尤其是針對電腦和電腦網路的。」

STL vector 效率小記

懶人看結論

用 C++ 寫程式,會用到 vector 來儲存陣列。用過的人都知道,用法大約是

vector<string> foo;
foo.push_back("Hello");
foo.push_back("World");

要拿單筆資料時,可以用 foo[1] 拿到 string("World")。要 loop 過全部資料時,寫

for (vector<string>::iterator it = foo.begin(); it != foo.end(); ++it) {
  //  *it 是字串資料
}
如果只要讀資料不改資料,可以用 const_iterator 代替 iterator。

用 push_back() 新增資料的一個特性是:如果 vector 的容量不夠,會自動配置新的記憶體空間(預設是兩倍大)、把資料拷過去,再把新資料寫入。

記憶體配置是很耗時的,能免則免。如果事先不知道所需的儲存量,這樣依需要配空間做是維持 vector 用 O(1) 時間取得資料、又不會浪費太多空間的好方法。可是如果事先知道要存 65 筆資料,還反覆去要 4、8、16、32、64 筆的空間,最後又用 128 筆的空間來存 65 筆,既浪費時間、又浪費空間!

所以 vector class 提供了三種指定長度的方法:reserve()、resize() 和 constructor 引數:

vector<string> a;  // 長度為 0
a.reserve(65);  // 預留 65 個元素的位置,沒有初始化
vector<string> b;  // 長度為 0
b.resize(65);  // 預留 65 個元素的位置,呼叫 string 的 default constructor
vector<string> c(65);  // 長度為 65

用在空的 vector 上,對慣 C 的人來說,reserve() 類似 malloc(),resize() 類似 calloc()。如果是在 constructor 給長度就有點像 char* c[65]; 這樣的陣列宣告。不過 C++ 和 C 還是不一樣,這邊的主要差異是物件,和物件的 default constructor、assignment operator 的行為,對效率有些影響。

先講講這三種做法的原理。

預留 reserve()

每個 vector 都有兩個重要的數字:容量(capacity)和長度(size)。容量是這個 vector 擁有的空間,長度是實際儲存了元素的空間大小,其值等於陣列的終點減起點。capacity 不小於 size 是個不變條件。

reserve() 的目的是擴大容量,做完時,vector 的長度不變,capacity 只會長大不會縮小,資料所在位置可能會移動。

reserve(N) 的做法很簡單:

  1. 如果 N <= 容量,不做事結束。
  2. 配置大小為 N 的空間,
  3. 把資料拷過去,
  4. 歸還原來的儲存空間,
  5. 更新陣列的起點、終點、容量。

因為 vector 一開始是空的,立刻預留顯然比填了資料後才預留省了拷資料的時間。

調整長度 resize()

調整長度目的是改變 vector 的長度,如果變小就擦掉尾巴的資料,如果變大就補零。更精確一點說,擦尾時會呼叫元素物件的 destructor,補零是補元素類型的 default constructor 產生的物件。補零如果會超過容量,會先預留空間,就是上面說的〔配置新空間、拷資料、歸還舊空間、更新陣列位置〕整個程序走一遍。

resize() 結束時,vector 的長度會改變為指定的大小,capacity 則視需要調整,確保不小於 size,資料所在位置可能會移動。

resize() 除了新長度 N 之外,還可以接受第二個引數,就是新元素的值,如果沒給就會用 default constructor 生一個來用。

在 constructor 指定長度

在 constructor 指定長度 N 的結果是一個容量和長度均為 N 的 vector,因為長度為 N,代表 N 個元素有資料,這資料就是元素類型的 default constructor 生出來的,或是用 vector constructor 的第二個引數給的物件。

這個 constructor 的做法也很簡單:

  1. 配置大小為 N 的空間,
  2. 設定陣列的起點、終點、容量,
  3. 把相同的值填入 N 個元素的位置。

效率

使用 vector 要注意的效率問題大致有兩點:
  1. 不做不必要的記憶體重配置:少依賴 push_back() 的自動記憶體配置,能自己要記憶體的就自己要,善用 reserve()、resize() 或 constructor 引數。
  2. 不做不必要的物件拷貝。比方說,要延長或建立一個 vector、但各個元素的值不同,不要用會填值的 resize() 或 constructor 引數,而是用 reserve() 再把物件一個一個 push_back() 進去。另外要注意的是,reserve() 要來的空間切不可用 operator[] 填值,除非元素是 POD。見下節。

少用 operator[]

既然寫了 vector,順便提一下 operator[]。一旦有個 vector<string> foo,可能會想用
foo[3] = "movie";
這種寫法,但要小心,這可能會 Segmentation Fault!
  • 第一,operator[] 不做邊界檢查,foo vector 的容量可能不到 4,foo[3] 就越界了。
  • 第二,foo vector 就算容量夠,但長度可能不到 4,foo[3] 是未初始化的記憶體,拿來當成 string 物件,就爆了,更不用說還要呼叫它的 assignment operator。但如果元素類別是 int、double、pointer 這類 POD(Plain Old Data),assignment 是用 memory copy 實作的,倒是不會出問題。

如果確定 vector 的各個位置都有物件了,但不確定 index 會不會越界(也許 index 是別人傳來的),除了自己檢查邊界外,也可以考慮用 at() 方法:

string that = foo.at(an_index);
foo.at(an_index) = "movie";
at() 會做邊界檢查,越界時會丟出 out_of_range 異常,比較容易 debug,必要時也可以把這個異常接住來處理。


2011年9月28日

重溫 Alice Cooper 的 Poison

前幾天在網路收音機上聽到 Alice Cooper 的 Poison,讓我一下回憶湧現...

台灣唱歌的好像一定要很純情或很傷情,這種描述慾念深到骨子裡的重搖滾,在台灣歌壇真的不容易聽到。忍不住把歌詞亂譯了,野人獻曝一下。

Your cruel device
Your blood like ice
One look could kill
My pain, your thrill

I wanna love you but I better not touch (Don't touch)
I wanna hold you but my senses tell me to stop
I wanna kiss you but I want it too much (Too much)
I wanna taste you but your lips are venomous poison

you're poison running through my veins
you're poison
I don't want to break these chains

Your mouth, so hot
Your web, I'm caught
Your skin, so wet
Black lace on sweat

I hear you calling and it's needles and pins (And pins)
I want to hurt you just to hear you screaming my name
Don't want to touch you but you're under my skin (Deep in)
I want to kiss you but your lips are venomous poison

你手段 殘酷
你冷血 如冰
看一眼 能殺人
我痛苦 你興奮

想要愛你 但我最好別碰
想要抱你 但理智叫我住手
想要親你 但我快忍不住了
想要嚐你 但你的唇是毒藥

你是流過我全身血脈的毒藥
你是毒藥
我不想掙脫這些鎖鍊

你的嘴 熾熱
你的網 捕我
你的膚 溼潤
黑蕾絲 香汗

聽你呼喚我 像是針在刺
想要傷害你 只為聽你喊我的名
不願撫摸你 但你已深入我身
好想要親你 但你的唇是毒藥

翻來覆去,好想、可是不該,再想、仍是不敢,連傷人的想法都出現了、最後還是退縮,完全是宅男碰到辣妹的心情啊!

拜網路之賜,現在不但可以在 YouTube 上找到原曲,Wikipedia 上列出的各種版本也找了不少。有這麼多不同流派的唱法,而且都還不錯,列出來方便以後回來聽。  :)


一、Alice Cooper 1989 年硬式搖滾原曲。

詞很內縮,曲很外放,配樂節奏就是爽快!

(對了,外套下好酷的 T-shirt!)








二、德國 Groove Coverage 2004 年的電子音樂版本。

不知道是怎樣的音樂環境,會讓這個團為這首曲子做了 21 種混音版?





三、澳洲〔外太空來的吸血僵屍〕 (Bloodsucking Zombies from Outer Space) 2005 年的版本。

之前沒聽過這個團,團名有夠 kuso。曲子前面聽起來和 Alice Cooper 的版本沒太大差別,副歌一進來我就笑得跌倒了!  XD




四、芬蘭女歌手 Tarja Turunen 2007 年的交響重金屬版本。

第一次聽到女主唱的交響重金屬,熱血啊!雖然她的音色太美太婉約了點,少了些重金屬橫衝直撞的感覺,但還是很想找她這張專輯來聽。





五、美國〔乾草種子迪西〕 (Hayseed Dixie) 2007 年的藍草版本。

實在太歡樂了!馬上想找身邊的女生勾起手來跳圈圈舞。  :)



六、德國的 DJ Gollum 在 2010 年混音的版本。

魔戒裡的咕嚕也來當 DJ 啦? XD    德國人好像真的很愛玩電子音樂!



七、2011 年 2 月福斯在以色列的 Passat 廣告

無人能敵的男主角哼唱的就是 Poison 的旋律配上自己的歌詞,最後當然要搞笑一下。



註:Poison 的官方 MV 有兩個版本,正常版的在 YouTube 上都是 240p 的,畫質太差不想貼;一刀未剪版的清楚很多、聲音也優,可是因為某種原因我不能貼,有慧根的人自己去找吧!  XDDD