如何打造一款java遊戲"外掛"

2022-01-10 下呀下

如何打造一款java遊戲的外掛?javaassist幫你找回飛機大戰遊戲開掛般的感覺...

java序列化機制為java對象的存儲和傳輸提供了一種高效的方案,序列化是將內存中的java對象轉為可見的字節流,而對應的反序列化操作可以從字節流恢復出該java對象,但java對象序列化的便捷和開放性同時也造成了安全問題。反序列化漏洞是java web應用中一種較為主流的漏洞類型,通過向漏洞接口傳入惡意反序列化對象,從而在執行java類反序列化操作時,readObject函數可能導致非預期的代碼/命令執行。

ClassLoader.defineClass是反序列化漏洞代碼中的常見函數,它具有從字節碼byte[]還原出一個Class對象的能力。如果輸入的類字節碼byte[]可控,則defineClass就會根據字節碼構造出可控Class對象,如果該Class對象被初始化,例如對象的newInstance()方法被調用,那麼可控類的static代碼塊就會執行,導致任意代碼執行。

javaassist是一個處理字節碼的類庫,能夠動態的修改class中的字節碼,在產生自定義類對象的字節碼時,非常方便,例如如下代碼:

ClassPool pool = ClassPool.getDefault(); // 獲取類池CtClass payload = pool.makeClass("EvilClass");     // 創建自定義類EvilClass類 payload.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet")); //設置類的父類為AbstractTransletpayload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");    //設置類的靜態代碼塊為運行calc命令byte[] evilClass = payload.toBytecode();    // 獲取自定義類的字節碼

代碼中創建了EvilClass類,並且在類定義的靜態代碼塊中調用了calc命令。

javaassist不僅可以創建新的類及屬性,並且具有改變運行時類屬性的能力,基於這種修改java應用運行時邏輯的能力,可以實現簡單的遊戲外掛。接下來我們嘗試使用javaassist打造一款遊戲外掛,從最經典的飛機大戰遊戲入手。

從github上找一款畫質較高的遊戲:

運行起來大概是這個畫面:

遊戲運行中發現了一個小缺點,就是飛機移動速度比較慢,使得遊戲玩家缺少了一絲緊張感。使用jd-gui查看遊戲jar的代碼發現,按住shift鍵可以加速。

16即為shift的鍵碼值,按下此鍵可以設置this.accelerate變量的值為true。同時在MyPlane類的move函數中如果檢測到this.accelerate值為true,那麼就增加飛機移動的步長,實現加速。

但是鬆開shift鍵就會取消對加速屬性的設置:

因此需要按住shift鍵才能實現保持飛機的加速狀態,多餘的按鍵操作降低了玩家的操作手感,並且敵機也會提高移動速度,那麼如何改進呢?如果可以修改應用運行時的move函數,在函數中加入自定義修改步長的代碼,就可以實現了。

幸好在java 1.5之後引入了java代理,這是一種可以對java應用運行時環境進行操作的方法,通過以下代碼可以實現:

int pid = 19344; VirtualMachine vm = VirtualMachine.attach(String.valueOf(pid));String agentJarPath = "javaAgent.jar" vm.loadAgent(agentJarPath); vm.detach(); 

使用VirtualMachine.attach函數附加到進程號為pid的進程jvm上,java進程id可以通過jps -l命令查看:

然後通過vm.loadAgent加載java agent jar文件,其中java agent jar文件中包含了修改程序運行時信息的代碼。

1、在manifest中指定Agent-Class屬性,其值為代理類全路徑。本例中為com.agent.plane


2、代理類需要提供public static void agentmain(String args, Instrumentation inst)或public static void agentmain(String   args)方法。並且在二者同時存在時以前者優先。



本例中agentmain代碼如下:


private static String className = "com.xiaoqing.game.MyPlane"; private static String methodName = "move"; 
public static void agentmain(String agentArgs, Instrumentation instrumentation) { System.out.println("agentmain"); instrumentation.addTransformer(new TestTransformer(className, methodName),true); try { Class[] loadedClass = instrumentation.getAllLoadedClasses(); for (Class c : loadedClass) { if (c.getName().equals(className)) { System.out.println("---find!!!---"); Method[] methods = c.getDeclaredMethods(); for(Method method : methods) {System.out.println(method.getName());} instrumentation.retransformClasses(c); } } } catch (Exception e) { } }

instrumentation.addTransformer()函數的參數即為修改類屬性的自定義transformer,該transformer需要繼承自ClassFileTransformer。transformer代碼如下所示:

public class TestTransformer implements ClassFileTransformer {        private String targetClassName;        private String targetVMClassName;    private String targetMethodName;
public TestTransformer(String className, String methodName) { this.targetVMClassName = new String(className).replaceAll("\\.", "\\/"); this.targetMethodName = methodName; this.targetClassName = className; }
@Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (!className.equals(targetVMClassName)) { System.out.println("not do transform:"+className); return classfileBuffer; } try { System.out.println("do transform:"+className); ClassPool classPool=null; try { classPool = ClassPool.getDefault(); } catch (Throwable e) { System.err.println("出錯了:" + e.getMessage()); e.printStackTrace(); } CtClass cls = classPool.get(this.targetClassName); CtMethod ctMethod = cls.getDeclaredMethod(this.targetMethodName); System.out.println(ctMethod.getName()); ctMethod.insertAt(92, "{ if (this.getClass().getSimpleName().equals(\"MyPlane\")) { step = 10.0; } }"); return cls.toBytecode(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } return classfileBuffer; }}

該類中需要實現的主要方法為transform,類加載時會執行該方法,其中參數 classfileBuffer為類原始字節碼,返回值為目標字節碼。

CtClass cls = classPool.get(this.targetClassName);CtMethod ctMethod = cls.getDeclaredMethod(this.targetMethodName);


可以看到通過以上代碼獲取了com.xiaoqing.game.MyPlane類的move方法對應的CtMethod對象,因為我們需要修改move方法,增加飛機的移動步長。


然後使用CtMethod類的insertAt方法插入修改步長的代碼:


ctMethod.insertAt(92, "{ if (this.getClass().getSimpleName().equals(\"MyPlane\")) { step = 10.0; } }");

在該方法的92行插入了修改步長的邏輯,並且通過this.getClass().getSimpleName()判斷當前類名稱是否為MyPlane,即為我方戰機,如果是則修改移動速度,實現外掛的效果。修改後的move方法如下:

public void move() {        if(accelerate){            step=Constant.PLANE_STEP+2;        }        else{            step=Constant.PLANE_STEP;        }                if (this.getClass().getSimpleName().equals("MyPlane")) { step = 10.0; }        if(up){            moveY(getY()-step);        }        if(down){            moveY(getY()+step);        }        if(right){            moveX(getX()+step);        }        if(left){            moveX(getX()-step);        }    }

加了攻速後的運行效果如下:

查看ctMethod.insertAt()的代碼實現,可以看到核心邏輯位於javaassist.compiler.Javac類的compileStmnt函數中,該函數將傳入的java語句解析為java語法的語句對象即Stmnt變量,並使用gen的atStmnt方法處理該對象生成字節碼:
public void compileStmnt(String src) throws CompileError {        Parser p = new Parser(new Lex(src));        SymbolTable stb = new SymbolTable(this.stable);
while(p.hasMore()) { Stmnt s = p.parseStatement(stb); if (s != null) { s.accept(this.gen); } } }

其中atStmnt方法如下,this.bytecode即為自定義語句對應的字節碼,此處根據java語句的表達式類型,向bytecode中加入了88這個字節。

轉載聲明:原創不易,如需轉載,請註明來源「下呀下」

歡迎加入網絡安全文檔免費分享大家庭!

「下呀下」,做一個有價值的公眾號。網絡安全標準規範、政策法規、趨勢動態、技術乾貨,海量優質資料免費分享!

加群方式:請先加管理員微信:xiayaxia01,備註:進群,管理員同意後即可邀您進群(加群人數較多,若未及時回復請見諒)。

關注「下呀下」,進入「文檔搜索」中心,下載更多網絡安全資料


相關焦點

  • 惡魔之血---Air Jordan 4 "Warcraft" custom 必須是AJ4至帥的一款
    據悉【惡魔之血---Air Jordan 4 "Warcraft" custom】這雙鞋已於 6 月 9 日至 10 日期間舉辦的
  • 「 茶爺"與 「 契約"
    「 茶爺"與 「 契約"文/正穰"茶爺"畫畫,原來叫「 茶嘴",所落畫款都是"茶嘴",別人問為何叫「 茶嘴",他就不告訴你。以至外地畫家知「 茶嘴"者多,知真名陳冰者少。直到有了小孫女,就自稱"茶爺"了。北京人叫"爺"敞亮「 ,"茶爺"叫起來也比茶嘴順溜,圈子內外又都改口叫他"茶爺"了。他依然是瘦小的身材,深色的大褂,左挎狗皮包。花白的小山羊鬍驕傲地翹著。「茶爺"與"契約"  扯上關係,與打官司沒關係。"契約"是真的,是過去人賣房子賣地用毛筆寫的文書,也有官府統一印製的文本,象現在的合同書。
  • "命根子"與"勞什子"
    "命根子"與"勞什子"      一 從賈寶玉性格的典型意義看曹雪芹人性之壯麗 說不盡的《紅樓夢》。
  • 譚志剛的"淡"與"雅"
    對於這些,僅年長我一歲的譚志剛,都有渉獵,而且大部分還十分精工。他是省書法家、省攝影家和省楹聯藝術家三個省級協會會員。作品多次在省級展出並獲獎,其作品廣泛被書籍收錄、收藏家收藏和拍賣。特別是他的微距攝影,構圖大膽而細膩,具有強烈的視覺衝擊力。為此,2014年8月,衡陽市委宣傳部主辦的"雁城市民課堂"還曾邀請他,主講微距攝影技巧的專題講座。
  • 一車一車的搬空貨架!一張照片流出,中國代購黨是如何"玩殘"他們的?老外氣得直跺腳~
    快到"黑五"了,北美這邊商家打折特別狠。不少朋友爆料,加拿大的商場(特別是Costco)已經被中國代購黨玩壞了!本地論壇最近流出一張照片,中國的人肉代購黨。。。一車車的從商品裡搬東西。全程包郵!SUKIN保溼乳是一款質感輕盈的乳霜,質地介於乳液和霜之間,味道是很淡的植物味。
  • 日本公布"處女率",真相令人吃驚
    然而島國雖盛產"愛情動作片"習俗卻十分保守只有和國際接軌的大城市才會相對開放日本的色情行業其實嚴格受政府控制未成年人是被禁止購買愛情動作片光碟的不久前公布的一份日本"處女率"報告,結果令人驚訝在日本20-24歲的女性中有45.4%是處女在不是處女的範圍中婚前沒有性經驗者高達70%日本國立社會人口問題研究所發布的調查報告也顯示日本18
  • 偽科學下所創造的"機器人大爺"!
    一聽說自己要去機器人大賽上丟人,於是果斷的跳樓"自殺"了!這一舉動讓他瞬間爆紅,成了網紅機器人。 一時間在全國乃至全世界引起巨大轟動。在經歷過一系列的"路轉粉再轉黑"的複雜過程之後。終於在救她的那段視頻中發現機器人頭頂有一個根頭髮!
  • 喝一罐就"斷片"?!北美夜店最流行的Four loko"失身酒"到底是什麼鬼?
    一罐Four Loko相當於:四罐百威+一罐紅牛+一杯咖啡。。。。這東西很危險,家長們要注意不過,作為一款含含酒精的果味飲料,Four Loko在任何國家都是被允許正常銷售的(就像酒一樣),大家也不要太敏感了。只要量力而行就好。。。(菜刀還危險呢,砍人還會死。正常社會都不會禁售菜刀。
  • 大叔的愛心:真實版"尋找威利"感動億萬人...
    你看過真實版的"立體尋寶書"嗎?有個建築工人童心未泯,趁工作之餘跟工地對面醫院病童玩藏寶遊戲,但其實背後藏著一顆體貼病童的善心,簡單的"尋找威利"遊戲竟成為病童每日的期待。這讓傑森開始想要為院童來點不一樣的餘興節目,旁邊的同事建議,"擺個真實版的威利如何?""嗯,這個主意不錯!"於是傑森立刻跟即將上大學的18歲女兒著手製作人型立牌。從小就擅長繪畫的傑森很快在手也很巧的女兒的協助下,完成了一個跟圖畫書中長得一模一樣的"威利",2.4公尺高的「威利」被擺在1,200坪大的工地。
  • 馬雲不去飯局,卻穿著女款"加拿大國寶"被媒體瘋拍!一件衣服的背後是加拿大人的堅持
    當時兩人系的領帶一紅一藍,很有CP感~馬雲特地選擇了纖瘦款型Fusion Fit,這款帽子和袖子都是為身材瘦小者設計的。淘寶大BOSS親自示範"買家秀",加拿大鵝又被炒了一波~其實,加拿大鵝羽絨服作為加拿大的名牌產品,這幾年一直都很火。但在中國國內有很多都是仿造品。(誰要告訴你幾百塊就能買到,100%都是假的!)
  • 丁嵐:"牧羊女"的"少林"情緣
    ,與電影《少林寺》中白無瑕扮演者丁嵐的一段"情緣。《少林寺》在全國各地的隆重上映,李連杰和丁嵐這樣的演員,根本不用"炒作"他們自然就是家喻戶曉的大明星,許多地方竟然出現萬人空巷一睹"少林寺演員"風採的生動場面。
  • 練功,為何要懂得"服食"
    人間最大的陰陽就是天地,陰陽二氣結合的產物即"精氣"!地球的外周有一層大氣,我們稱為大氣層。大氣層包裹著地球,按照傳統說法,這個大氣層就是天,地球本身是地。所以古人講天包地外,這是講地球這個世界本身的天地。從我們人的角度來看,腳下是地,頭上是天。人處於天地之中,人的這個身體,是天地二氣結合的一種狀態。
  • 惹翻臺妹的香港"性格"小店
    這其中就包括,本地特產:"性格"小店。    現存最有名的當屬澳洲牛奶公司,一間名不符實,以服務態度粗暴,卻每天大排長龍的茶餐廳。影視作品中,最經典的當屬,周星馳和張學友合拍的《咖哩辣椒》中,對客人毫不妥協的捲毛茶餐廳老闆。   臺妹慕名而去高雄的香港甜品店,老闆先是堅稱"太極"為"黑白",更在甜品中敬奉中指圖案,令臺妹憤而網絡撻伐。
  • Emoji表情符號添72新丁:"打臉"、"流口水","孕婦"...你一定要試試
    你的手機裡很快就可以用上"與時俱進"的72新添Emoji表情符號。其中的"大神級"的表情符有:"在地板上打滾且大笑"及"一個在自拍的手"!蘋果和微軟反對"步槍"emoji制定新的表情符過程中一個值得玩味細節是,作為奧運會運動項目之一的"步槍射擊"emoji最後被踢出了列表。 "病毒式傳播"大神Buzzfeed News的透露的內幕是,只是蘋果公司和微軟反對的結果。這個消息在社交網絡上引起了討論。
  • 被誤讀的"大表哥"丹·史蒂文斯
    等待是值得的,反差之下"大表哥"的顏值直登宇宙巔峰!話說,"大表哥"的暱稱是怎麼來的呢?當然是源於粉絲心目中的經典《唐頓莊園》。不過,粉絲們也許並沒有留意到,"大表哥"其實應是"大堂哥",絕非大表哥。在《唐頓莊園》中,作為伯爵的繼承人,馬修是伯爵的遠親,同樣姓"克勞利",用他自己的話說,他是隔了三代的旁親,即他的爺爺的爺爺和伯爵的爺爺的爸爸是親兄弟。所以,馬修和伯爵家的大小姐瑪麗是堂親關係,絕非姻親關係。
  • "Senior Salute":強姦案揭露了美國名校黑暗性文化!
    這場強姦案發生在一個稱為"Senior Salute"的傳統活動中,在此期間,即將畢業的男生會想辦法奪去低年級女生的貞操。Labrie承認,這並不是男生之中的唯一的性競爭遊戲,他們還會在洗衣房的牆上記下流水帳,來確定誰睡的處女最多,他告訴警方希望自己能得第一名。
  • 日本歷史上最多人出鏡的"毛片":百名女優廢棄鄉村學校拍"小電影"全記錄!
    "的攝製組。這部作品要今年九月份才能發行,雖然時間尚早,但是由於參演人數眾多,如何在一天之中精心安排充分利用拍攝場地是非常考驗攝製組能力的。"一樣,由多段"如實記錄"的片段組成,全片可以總結為教職工追著女學生滿學校跑。
  • 均安,你為什麼這麼"窮"?
    但是一直以來,均安鎮的社會經濟發展水平一直在順德四街六鎮之中處於落後墊底的位置,被順德人稱為"窮"均安。"        在均安鵬泰百貨招商中心裡,每天都在邀約著來自廣東各地的品牌商家和代理商來訪,但是這些商家中的絕大部分都表達了相似的意見,那就是一一均安太"窮"了,他們的店不能開到這裡來。
  • 抱歉,這部9.2分的"喪片"推晚了
    每年都會有新的潮流風颳來,而今年的除了"佛系"以外最有名的,可能就是"喪"。當然,這不是一個貶義詞。我認為,"喪"可能只是人們對於自己生活的一種自嘲,對社會的一種無力的妥協。昨天那部「她不知道名字的那些鳥兒」,喪氣十足。
  • 講講"電視"
    講講"電視機"(滬語專創專版)馮濟民(謝謝儂個關注!