RGSS 中執(zhí)行機器碼

給大家認識一下肢执,這是我們今天的主角↓

CallWindowProc

CallWindowProc = Win32API.new 'user32', 'CallWindowProc', 'pLLLL', 'i'

這個 API 接受 5 個參數(shù)枉阵,p 是機器碼(字符串)的地址,四個 L 是可選參數(shù)预茄,返回值由 %eax 帶出岭妖。

符號 含義 說明
p *pointer RGSS 為 32 位運行環(huán)境,在這里是 4 字節(jié)的
L unsigned int pack 的時候正負數(shù)無關反璃,例如 [-1].pack('i')[-1].pack('L') 得到的結果是一樣的
i signed int unpack 的時候正負數(shù)有關昵慌,[-1].pack('L').unpack('L') 會得到 2^32-1

A+B

考慮一個匯編子程,參數(shù)為兩個 int档痪,將求和后的結果保存到 %eax裁眯。

sum:
  push %ebp
  mov %esp,%ebp
  mov 8(%ebp),%eax  # 第一個參數(shù)
  add 12(%ebp),%eax # 第二個參數(shù),直接加給 %eax
  leave
  ret $8 # 兩個 int = 4 * 2

實際上堆棧框架(push ebp ~ leave)是有點浪費字節(jié)的,我們把它去掉:

sum:
  mov 4(%esp),%eax # 第一個參數(shù)
  add 8(%esp),%eax # 第二個參數(shù),直接加給 %eax
  ret $8 # 兩個 int = 4 * 2
指令 機器碼
mov 源(右)是寄存器 0x8b ModR/M SIB Disp Imm
add 源(右)是寄存器 0x03 ModR/M SIB Disp Imm
ret imm16 0xc2 Imm16

上面這段子程的機器碼可以翻譯為:

[
  0x8b, 0104,0044, 4,  # [0] mov 4(%esp), %eax
  0x03, 0104,0044, 8,  # [1] add 8(%esp), %eax
  0xc2,          8,0,  #     ret $8
].pack('C*')

更多機器碼參考這里

由于我們一開始寫了四個 L 參數(shù)的聲明踩官,這里修正為 ret $16辩越,然后我們試一下這個 API:

p CallWindowProc.call [
  0x8b, 0104,0044, 4,  # [0] mov 4(%esp), %eax
  0x03, 0104,0044, 8,  # [1] add 8(%esp), %eax
  0xc2,         16,0,  #     ret $16
].pack('C*'), 3, 5, 0, 0

(RGSS3 請使用 msgbox 或者打開控制臺選項來看輸出)

Bitmap

下面我們泄露一個 Bitmap 的內存結構:

[0,0,0,0,[0,0,[0,0,0,0,pRData]]]

RData 里存的是每個像素的 BGRA 信息督惰。另外,RGSS 中 object_id * 2 是 Bitmap 對象的真實地址位置。

0 代表四字節(jié)數(shù)據(jù)并且不關心割笙,我們要得到這個 pRData

class Bitmap
  GETADDR = [
    0x8b, 0104,0044, 4,  # mov  4(%esp), %eax
    0x8b, 0100,     16,  # mov 16(%eax), %eax
    0x8b, 0100,      8,  # mov  8(%eax), %eax
    0x8b, 0100,     16,  # mov 16(%eax), %eax
    0xc2,         16,0,  # ret $16
  ].pack('C*')
  def addr
    @_addr ||= CallWindowProc.call GETADDR, object_id * 2, 0, 0, 0
  end
end

有了位圖數(shù)據(jù)的首地址,就可以開始搞事了:

Pixel

首先泄露一下位圖數(shù)據(jù)的內存形式為:

BGRABGRABGRABGRABGRABGRABGRABGRA...

width * heightBGRA扔字。

考慮一個簡單的反色算法:把每個 pixel 的 BGR 數(shù)據(jù)都取反。

C 語言形式如下:

for (int i = 0; i < length; ++i)
  data[i * 4] ^= 0x00FFFFFF; // AARRGGBB

不難寫出這樣的代碼:

def callproc code, a = 0, b = 0, c = 0, d = 0
  code = code.pack 'C*' if Array === code
  CallWindowProc.call code, a, b, c, d
end
class Bitmap
  INVERSE = [
    0x8b, 0104,0044, 4,  # mov  4(%esp), %eax   addr
    0x8b, 0114,0044, 8,  # mov  8(%esp), %ecx   length
    0x81, 0060,   0xff,0xff,0xff,0x00,
                         # xorl  (%eax), 0x00FFFFFF # 0+1|4&5-6^
    0x83, 0300,      4,  # add       $4, %eax
    0xe2,          -11,  # loop     -11
    0xc2,         16,0,  # ret      $16
  ].pack('C*')
  def inverse!
    callproc INVERSE, addr, width * height
    self
  end
end
反色

下面我們再寫一個套才,偽色差效果:把整個圖的某個通道整體左/右移 offset 個像素。

C 代碼類似下面這樣:

// phase  通道携兵,假設一定是 0,1,2,3 中的一個
// offset 偏移像素距離,可能為負數(shù)
for (int i = 0; i < length; ++i)
  data[i + phase] = data[i + offset * 4 + phase];
// 上面一定會產生越界錯誤广恢,我們修正一下
if (offset == 0) return;
length -= abs(offset);
if (offset > 0)
  for (int i = 0; i < length; ++i)
    data[i + phase] = data[i + offset * 4 + phase];
else // offset < 0
  for (int i = length; i > 0; --i)
    data[i - offset * 4 + phase] = data[i + phase];

出來的機器碼大概是這個樣子:

class Bitmap
  SIMPLEABERRATION = [
    0x8b, 0104,0044, 4,  # [0] mov  4(%esp), %eax   addr
    0x8b, 0114,0044, 8,  # [1] mov  8(%esp), %ecx   length
    0x8b, 0164,0044,12,  # [2] mov 12(%esp), %esi   offset (can be neg)
    0x03, 0104,0044,16,  # [3] add 16(%esp), %eax   phase (% 4)
                         # ------------------------------- #
    0xbb,      4,0,0,0,  #     mov       $4, %ebx          #
    0x83, 0376,      0,  #     cmp       $0, %esi          #
    0x74,           23,  # .-- je        23                #
    0x7f,           10,  # |.- jg        10                #
    0x8d, 0104,0210,-4,  # ||  lea -4(%eax,%ecx,4),%eax    #
    0xf7, 0333,          # ||  neg    %ebx                 #
    0x01, 0361,          # ||  add    %esi , %ecx          #
    0xeb,            2,  # ||  jmp        2             -. #
    0x29, 0361,          # |'- sub    %esi , %ecx        | #
    0x8a, 0024,0260,     # |.- movb  (%eax,%esi,4),%dl  -' #
    0x88, 0020,          # ||  movb    %dl ,(%eax)         #
    0x01, 0330,          # ||  add    %ebx , %eax          #
    0xe2,           -9,  # |'- loop      -9                #
    0xc2,         16,0,  # '-- ret      $16                #
  ].pack('C*')
  def simple_aberration! offset = 5, phase = 2 # Red [B,G,R,A][phase]
    callproc SIMPLEABERRATION, addr, width * height, offset, phase % 4
    self
  end
end
偽色差

小朋友們學會了嗎 ;)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末侍瑟,一起剝皮案震驚了整個濱河市咐低,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖堰汉,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件就乓,死亡現(xiàn)場離奇詭異,居然都是意外死亡噩翠,警方通過查閱死者的電腦和手機伤锚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門徘铝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來废登,“玉大人,你說我怎么就攤上這事梁钾∧沸海” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵冒嫡,是天一觀的道長拇勃。 經常有香客問我,道長孝凌,這世上最難降的妖魔是什么方咆? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蟀架,結果婚禮上瓣赂,老公的妹妹穿的比我還像新娘。我一直安慰自己片拍,他們只是感情好煌集,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捌省,像睡著了一般苫纤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纲缓,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天卷拘,我揣著相機與錄音,去河邊找鬼祝高。 笑死栗弟,一個胖子當著我的面吹牛,可吹牛的內容都是我干的工闺。 我是一名探鬼主播乍赫,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼瓣蛀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了耿焊?” 一聲冷哼從身側響起揪惦,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罗侯,沒想到半個月后器腋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡钩杰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年纫塌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讲弄。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡措左,死狀恐怖,靈堂內的尸體忽然破棺而出避除,到底是詐尸還是另有隱情怎披,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布瓶摆,位于F島的核電站凉逛,受9級特大地震影響,放射性物質發(fā)生泄漏群井。R本人自食惡果不足惜状飞,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望书斜。 院中可真熱鬧诬辈,春花似錦、人聲如沸荐吉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稍坯。三九已至酬荞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瞧哟,已是汗流浹背混巧。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勤揩,地道東北人咧党。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像陨亡,于是被迫代替她去往敵國和親傍衡。 傳聞我的和親對象是個殘疾皇子深员,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內容