Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

アカツキでのインターンを終えて 〜フルリモートでスマートフォンゲームの機能改修をしてきました〜

こんにちは、はじめまして。
daimond-arrowです。オタクをやっている大学院生です。
好きなアニメはグレンラガン、今季の一押しは球詠です。 

 

このたび、アカツキさん(以下、敬称略) で
フルリモート型の短期インターンシップ (以下、インターン)
に参加させていただきました。
せっかくの機会なので、インターンを終えての所感をここに残しておきたいと思います。

 

この記事が、

  • これからインターンに参加しようと考えている学生
  • アカツキのことを知りたいという方
  • スマートフォンゲーム開発をしている企業ってどんな感じなんだ?と気になっている方
  • そして、フルリモートのインターンシップってどうなんだ?と疑問に思っている方

にとって、参考になれば嬉しいです。

 

目次 

 

インターンに至るまで

さて、気になるインターンの中身の前に、少しインターンに至るまでの経緯を説明させていただければなと思います。
そんなことよりインターンで何をするかが気になる!、という方は飛ばしてこちらから読んでいただければと思います。

 

まずアカツキとの出会いは、昨年8月の就活イベントでした。
自分が個人・研究室でのUnity開発経験があったことから声をかけていただき、まずは会社見学からということでアカツキのことを知っていきました。
このとき、自分で何かを開発したことがあるという経験が、就活ではかなりアドバンテージになるんだなあと小学生並の感想で思いました。もとい、ゲーム開発をしている企業とマッチする、でしょうか。これから就活という方は一つ参考にしてください。

オフィスに遊びに行かせてもらった際には、その綺麗さにかなり驚きました。オフィスにバリスタがいるのは圧倒的にずるいですね......(私は無類のコーヒー好きなので)

 

 

あれやこれやで話が進んでいき、このインターンのことが決まったのは昨年(2019年)の12月頃でした。じゃあ3月末からインターンしましょうか!という話だったのですが、そこで今回のコロナウイルスでの外出自粛。
インターンもなくなってしまうかなあとすら思っていたのですが、自分がインターンには参加したいです!と主張をすると、アカツキは柔軟に対応してくださいました。
提案していただいたのは、フルリモートでのインターン受入。
こういったところに柔軟に対応してもらえたのはとても嬉しかったですし、そのキャパシティがあるいい会社だなと素直に思いました (後にも述べますが、フルリモートで全く問題なく、むしろ快適に楽しくインターンさせていただきました) 。

 

このようにして自分のインターン参加の日程が決まりました。
ではこれから、本格的にインターンで何をしたのか述べていきたいと思います。

インターンで参画したタイトル

今回インターンで関わらせていただいたのは、アカツキを代表する(と思う)スマホゲーム『八月のシンデレラナイン』━━ 女子高生が甲子園を目指すアツいゲームです(少なくとも私はそう感じています!)。アニメ化もしてます(寺で合宿する回が最高です)。

f:id:diamond-arrow:20200529130414p:plain

そしてこれは色眼鏡ではないのですが、かなり面白いゲームです。個人的にはやればやるほど面白い、やり込み要素のあるスルメゲームだと思っています。
自分がプレイを始めたのはインターン参加3ヶ月前からなのですが、かなりハマってしまいました。
参考程度に自分のプレイログを載せておきます、自分が色眼鏡で言っているわけではないというのがわかっていただけるかなと思います。

f:id:diamond-arrow:20200529131019p:plain

インターン中の業務

さて、タイトルは先に述べた通りですが、具体的にインターン中に何をしたんだという話になると思います。
自分はクライアントエンジニアとしてインターンに参加しました。

開発に使用したのは、主にUnity C#、たまにSQLを叩いたりしていました。

 

f:id:diamond-arrow:20200529131051p:plain

業務内容は、クライアントサイドの機能改修。
今ある機能を変えてゲームを快適にしましょう、というものです。

基本的にインターン生には、一人一人にメンターがついてくださり、チームでの開発にジョインします。質問があればチャットやオンライン通話でメンターやチームの皆さんにすぐに聞けたので、困った事は全くありませんでした。

以下、自分がインターン中に行ったことを3つに分けて紹介したいと思います。

自分のユーザーデータの可視化

自分はかねてより、スマホゲームのデータはサーバー上でどのように保存されているのだろうかと興味を持っておりました。
そこでメンターの方に、ログを見せてください!と頼んだところ、快く見せていただきました。

そしてせっかくログを見せてもらうのだからと、軽く自分のユーザーデータを可視化してみたものが、先ほどのプレイログのグラフです。
クライアントエンジニアとしてのインターン参加ということでしたが、領域外のこともチャレンジさせていただき、大変感謝しています。チームの方にも面白いねと言っていただき、アカツキはチャレンジに対してとても寛容な会社だとしみじみ実感しました。

 

 

戦術機能の改修:オペレーションコストに応じた停止機能の追加

クライアントエンジニアとしての最初の仕事は、戦術機能の改修でした。
少しだけ、前提の話をさせていただきましょう。

ハチナイには戦術機能というものがあります。ハチナイでは、キャラクターが選手として野球をし、相手チームと得点を競うのですが、この選手に指示が出せるのが戦術機能です。例えば、打席に立った選手に[送りバント]を指示したり、ピッチャーに[全力投球]を指示できます。
他方、ハチナイはこの試合をオートで進めることができます(周回が非常に楽!)。そしてそのオート機能にはオプションがあり、試合が[ピンチやチャンスのときのみ停止する]というものがあります。つまり、オートだけど試合に負けているときはプレイヤーとして介入して、戦術機能を使えるよう停止する設定にする、ということができるのです(便利!)。

そして以前まで指摘されていたのは、この停止がオペレーションコストがない場合でもピンチ・チャンスだったら停止する、という問題でした。
戦術を使いたいからオートを停止するのに、オペレーションコストがない場合でも止まってしまうのはユーザーにとって嬉しくありません。

f:id:diamond-arrow:20200529131219p:plain
 

 

そこで自分がクライアントサイドとして取り組んだのが、この機能改修でした。

ロジックとしては単純に、オペレーションコストが足りているかチェックする関数を、既存のロジックに入れ込むというだけで済みました。
さらに幸いなことに、既存のコードで応用できそうな部分があったので、すぐに改修できました。こういったところは、設計がしっかりしていたからかとも思っています。

そして嬉しいことに、インターン期間中にアップデートに盛り込んでもらえるという嬉しい体験をすることができました。この体験はとても嬉しく、ゲーム開発の一つの醍醐味を実感した瞬間でした。

 

 

サーバーサイドと連携しての機能改修:デレストオーダー編成選手の移籍

上記の改修に加え、もうひとつの改修にトライしました。
こちらは、デレストオーダーに編成中の選手を移籍できるようにする、という機能です。

デレストは、普通の試合とは別に用意された別種の育成要素です。こちらもある種試合のようになっており、選手をオーダー編成してチャレンジします。そしてこの編成は自動で保存されるようになっています。

他方、ハチナイでは、キャラクターの売却機能を[移籍]と呼んでいます。この移籍では、ある種のロック機能として[オーダーに編成中の選手は移籍できない]ようになっていました。

ここで問題になっていたのは、移籍させたい選手をデレスト編成から外すことが手間であった、ということです。

f:id:diamond-arrow:20200529131323p:plain


 

次に取り組んだのはこの課題でした。

そしてこの課題には、クライアントサイドだけでなく、サーバーサイドの改修も必要となっていました。移籍や編成についてはサーバー側の処理も入るからです。

そこで自分は、インターン同期のサーバーサイドエンジニアと協力し、二人でこの課題を解決しました。
毎日チャットや通話で、どちらがどこまで担当するのかを話し合い、お互いに問題がないか確かめ合う時間が続きました。

嬉しいことにこちらもお互い完成し、あとはリリースのみ、というところまでやりきってのインターン終了となりました。

この経験は、チーム開発の肝である密なコミュニケーションの重要性、そしてチーム開発の楽しさ(なぜか二人で開発するということがすごく楽しかった)を感じる良い機会になりました。また同時に、クライアントに閉じず、サーバーサイドにも触れてみようと思える非常に刺激的な機会であったと感じています。

 

インターンで得たもの

以上が自分がインターン中に行ったことの詳細になります。
上記の他にも、アカツキでのインターンは得るものが多いインターンでした。
特に良かったと思うのは以下の2点です。

リッチなコーディング経験

まず、非常に丁寧なコードレビューをいただきました。
自分のプルリクエストに対して、かなり綿密なコメントや改善案をいただき、自分のコーディングスキルの向上が実感できました。

さらに、チームの人が書いたコードをレビューするという機会もいただき、兢々としながらもレビューさせて貰ったのはいい経験でした。

他にも、そもそもの設計がどうなっているのかを知れたり、コーディング規約や実戦での書き方を知ることもでき、非常に糧になる経験でした。

上流からリリースまでの流れを実感

コーディングだけに留まらず、そもそも機能がどう決まるのか、リリースまでにどういう流れを取るのかということを知ることができました。

また、アカツキならではだなと感じたのは、自分が生意気にも「ここも改善してみたいんですけど、どうでしょうか!?」などと提案したことがスルッと受け入れてもらえたことでした。アカツキはエンジニアの意見が取り入れてもらいやすい環境のようです。
こうした提案が通りやすいということは、自分がこのゲームをよくしているんだ!というある種のやりがいが発生しやすいということで、確かにチームの皆さんの士気も高い水準であると感じました。

きっと今後も、このゲームはどんどんよくなっていくだろうなということが確信できることが知れたのも、1ユーザーとして嬉しかったです!

おわりに

アカツキでのインターンはとても楽しく充実したものでした!
メンターの方、チームの方、人事の方、お話しさせていただいた新卒の方、インターン同期、みなさまに感謝しています!ありがとうございました!

そして、この記事を読んでくださった方、ありがとうございました!
こんな記事ですが、アカツキの良さ、ゲーム開発のこと、フルリモートインターンのことなど、参考になれば幸いです!


参考:成果発表資料

 

サーバーサイドでのインターン(五月)の成果報告

まえがき

お初にお目にかかります。 株式会社アカツキさんで五月十一日〜五月二十二日の約二週間(実質十日間)、サーバーサイドの開発でインターンをいたしました、村上と申します。

本記事では、当該インターンにおける成果報告と感想を述べます。よろしくお願いいたします。

インターンの形態について

時期が時期の中行われたインターンですので、皆様に誤解を与えてしまわないよう、まずは本インターンの形態についてご説明いたします。

ご存知の通り、現在、世界中が感染症対策に追われています。日本も例外ではなく、具体的には、オフィスへの出勤を最小化しなければなりません。 ですので、アカツキさんも全面的にリモートワークを行なっています。そのため、今回のインターンは対面を一切廃したフルリモートで行われました。私は愛知県在住なので、東京とおよそ300kmのソーシャルディスタンスを確保した上での実施となります。

機材は事前に郵送いただき、手続き等も全てリモートで行われました。インターンに際して、感染症対策は徹底されていたという点を明記しておきます。

インターンで行ったこと

本インターンでは、大人気ソーシャルゲーム『八月のシンデレラナイン』、通称ハチナイのサーバーサイドの開発業務に携わりました。なお、サーバーにはRailsが用いられています。

10日間中は様々なタスクがありましたが、その中でもメインで行ったものは以下の三つです。

  • APIサーバー開発環境の改善
  • 敵チーム調整用管理画面の作成
  • デレスト編成中の選手をそのまま移籍・保管庫に移動させられる機能の実装

それぞれについて、詳しく述べていきます。

APIサーバー開発環境の改善

インターンを開始してまず手をつけたのが、この作業です。 当時のAPIサーバーの開発環境には以下の問題があり、環境構築におよそ半日ほどかかってしまっていました。

  • 開発用のMac上にそのままRailsやMySQLなどをインストールしていたため、依存するソフトウェアやライブラリのバージョンを適切に揃える必要がある
  • 環境についてのドキュメントが不足しており、構築する側がトライアンドエラーを繰り返して設定する必要がある

一度構築してしまえば問題ないとはいえ、今後入ってくる方にも同じ時間を強いてしまうのは勿体ないこと、さらに非サーバーサイド開発でも手軽にローカルで検証環境を立ち上げられるようにしたいということで、この改善に取り組むことにしました。

対応方針としては、DockerとDocker-Composeを用いて数コマンドで環境を立ち上げられるようにして、誰でも簡単に環境を作成・破棄できることを目指しました。 幸い、作りかけでしたが既にdocker-compose.ymlと関連ファイルが作成されたブランチがあったため、出ているエラーの調査(連携するその他のソフトウェアのメンテナの方からの聞き取り等含む)と修正をしたり、一部テストケースの改善をしたり、ドキュメントを整えたりといった細かな作業を行い、実作業二日間、計三日間でApproveをいただけました。

この改善による影響は大きく、半日かかっていた構築作業がおよそ20分で完了するようになりました。また、ゲームのクライアントを担当されている方と一緒に開発をする際、相手側で検証用サーバーを立ち上げてもらって開発を進める、といった手法も気軽にとることができるようになり、開発の体験が向上しました。 実際に「便利になったね!」といったフィードバックをいただけた時は、本当に嬉しかったものです。

敵チーム調整用管理画面の作成

次に対応できそうなタスクを探していると、『敵チームの調整を管理画面から行えるようにする』といったタスクのカードが目に留まりました。 詳しく話を聞いてみると、ゲームの調整を行う方からの運用改善として以下の課題が出ていたことが分かりました。

  • 試合の敵チームを作成するにあたって、現状は職人技で行なっているので、属人化してしまっている部分がある
  • 敵チーム調整のサイクルが一つの場所で完結しておらず、結果の予測も簡単ではないため、経験が浅いと調整に時間がかかってしまうのが原因
  • そのため、管理画面に敵チーム調整用の機能を追加し、管理画面の機能群だけで調整を完結させられないか

お話を伺う限り自分でも対応できそうだったので、そのまま着手することにしました。 具体的には、ActiveAdminで作られていた管理画面に敵チーム調整用のページを新設し、関連するパラメータも調整できるようにしました。

ActiveAdminの挙動で少し詰まったところはありましたが、それ以外はすんなり実装できたと思います。実装後に簡単なドキュメントも書いたのですが、良い勉強になりました。レビュー含め二日間ほどで終わったと思います。

デレスト編成中の選手をそのまま移籍・保管庫に移動させられる機能の実装

こちらは、ゲームのクライアント側でインターンをされていた方との共同作業になります。 ハチナイの試合やデレストにおいて、今までは以下の問題がありました。

  • 試合やデレストを進めていて選手所属数上限エラーとなった際、デレスト編成中の選手はそのまま移籍や保管庫に移動させることができず、いちいちデレストの画面から入れ替えを行う手間があった

そのため、サーバー側とクライアント側の両方に変更を加え、デレスト編成中の選手でもそのまま移籍・保管庫への移動を行えるように改善することになりました。 サーバー側の変更量自体はさほどだったのですが、変更の内容と影響範囲を考慮し、テストケースの修正と追加をメインに行いました。実際にテストを増やしてみると、実装中は気がつかなかったケアレスミスが発見できたりして、やはりテストを増やすのは正解だったなと実感しました。こちらもレビュー含め、三日間ほどで完了できました。

また、実装に際して、クライアント側のインターン生の方がとても優秀で頼もしかったです。 リモートで実装に関しての相談や打ち合わせを何度かしたのですが、毎回スッと意を汲んで対応していただけたので感謝しています。 円滑な開発を行う上で、コミュニケーション能力は本当に大事ですね。私も精進します。

学び

実質10日間という短い期間でしたが、インターンを通して学べたことは多くありました。

例として、分かっているはずだったものが、実際に手を動かしてみると頭からすっぽり抜け落ちてしまう、といった問題を認識できたことが挙げられます。 具体的には、実装における設計です。頭の片隅に置いてあったベストプラクティスのはずなのに、作業に集中していると目の前のことで一杯一杯になってしまい、後から改善点を指摘される、といったことがありました。 もちろんインターンというアウェーな環境というのもあるとは思うのですが、それ以上に自分の経験不足を感じたのが大きいです。頭をよく使ってから手を動かす、ということを繰り返すことで、どんな状況でもベストプラクティスが実践できるようにしていきたいものです。

また、これはいろんな場所で何度も言われていることだとは思うのですが、チーム開発においてコミュニケーションは重要だなと思いました。 アカツキさんの方々は皆さんお優しくて、Slack上でもいろいろなトピックで会話が弾んでいます。そのおかげで気軽に質問や発言ができましたし、結果的に円滑な作業に結びついていたと感じました。 これが、仮に最低限の会話しかないような状況だったとしたら、インターンというのも相まって、萎縮や虚無感で効率がガタ落ちだっただろうなと容易に想像できます。 リモート作業ではどうしても人との関係性が希薄になりがちで、恐らくこの状況はこれからもしばらく続くと予想されますが、こうしたコミュニケーションが効率という面を支えているということを忘れないようにしたいところです。

感想

インターンが始まるまでは、寝付けずにうなされるくらい、自分がやっていけるのかどうかが心配で仕方ありませんでした。 しかし、実際にサーバーサイドのチームに入って作業してみると、思っていたよりかはパフォーマンスが出せたので一安心です。とはいえこれで傲慢になるのではなく、学んだ点を糧に引き続き精進していきたいと思います。

また、仕事がとても楽しかったです。毎日十時〜十九時までが勤務時間だったのですが、十九時に業務が終わってすぐに次の日の朝が待ち遠しくなるほどでした。 自分でもこの感情には驚いたのですが、それだけアカツキさんが働きやすい環境だったのかなと思います。まさにハートドリブンですね。

さいごに

大変な情勢の中、就職活動の一環とはいえインターンの受け入れをしてくださり、お世話になったチームの皆さんやアカツキさんには大変感謝しております。 ありがとうございました。

【ハチナイ】Unityクライアントエンジニアインターン【9日間】

こんにちは。teppeiと申します。3月16日〜3月27日まで、祝日を挟んで9日間インターンをしました。「八月のシンデレラナイン」のプロジェクトでUI関連の機能を中心に開発に携わりました。本記事では今回のインターンで行なったタスクや、自分の感じたことなど書いていきたいと思います!

 

目次

 

自己紹介

私は機械&情報系の大学院一年生で、VRやヒューマンコンピュータインタラクションの研究をしています。普段はVTuberの配信システムを作る会社でバイトをしています。インタラクティブで新しいエンタメを作る仕事をしたいので、それが実現できそうな会社を探して就活中です。

 

 インターンに参加した経緯

私は去年夏にあったアカツキのゲームジャムに参加し、その後選考を進めてアカツキから内定を頂いていました。就職先を決めるにあたってもう少しインターンを経験して判断材料を増やしたかったので、今回のインターンに参加させていただきました。

 

 初日〜作業開始まで 

 初日に同時に入社した方々と一緒に、人事、ゲーム部門、労務のオリエンを受けました。それぞれの時間は短く、簡潔にまとめられていたので受けるのが楽で良かったです。オリエンの合間に業務用MacBook Proの環境構築を進めていました。

二日目にメンターと開発プロデュサーの方と三人で、私が事前にゲームを遊んで気づいた改善点リストを見つつ、インターンで行うタスクを決めるミーティングをしました。タスクはすんなり決まり、ストーリーチャプターのレイアウトを自動で配置するUnityEditor拡張を作ることになりました。その日の午後から本格的に開発を始めることができました。

参加したチーム

「八月のシンデレラナイン」という、野球をする女子高生を育成するモバイルゲームを開発しているTSUBASAというチームでインターンさせていただきました!

ストーリーチャプター自動レイアウト機能の開発

方針の決定

ストーリーチャプターのアイコンはプランナーの方々がその都度位置を手打ちしているのですが、通常ステージではレイアウトが定型(波形など)のものも多いので、そういったレイアウトを自動化して手間を省けないかというのが今回のIssueでした。

まず最初に実際にレイアウト作業を行なっているプランナーの方々の席まで行って、現在のワークフローと、改善したい点を教えていただきました。

レイアウトの座標はUnity上でScriptableObjectに直接打ち込んでいるとのことだったので、同じくUnity上で作業ができるように、Unityのエディタ拡張で自動レイアウト機能を作っていく方針にしました。また、打ち込んだ座標が正しいかどうかはその都度ゲームを実行して確認しているとのことだったので、実行しなくても手軽に確認できるようにGUIを実装することにしました。

エディタ上でレイアウトを編集できる機能の実装

この前webで見かけたプレハブ編集画面を自分で作るというアプローチが良さそうだったので、ScriptableObjectに書かれたアイコンレイアウトの情報をSceneView上に表示して、GUIで編集・保存できるようにしようと考えました。

f:id:negitoro113:20200325144600p:plain

実際に作ったものの画面がこちら ↑ です。赤い四角がアイコンの位置を表しており、左上にあるGUIで数値を変更するとSin波や三角波の形状にアイコンが自動配置されるようになっています。

この機能がそれなりに動くようになった時点で実際に機能を使う方々に見せに行き、フィードバックを頂いて機能改善をしていきました。

三日目にはだいたい動くようになったので、プルリクを出してコードをレビューしていただきました。細かい部分まで丁寧にレビューコメントをいただきました。普段のバイトでは開発に携わる人数が少ないということもあり、そこまで細かくはレビューされないので、新鮮でいい経験になりました。

プレイ中に編集・保存を行えるように実装方針を変更

既存のコードやプランナーの方の要望への理解が深まっていくにつれ、もっと使いやすい設計が思い浮かんできました。

これまでの実装だとアイコンの位置が赤い四角で示されていましたが、実際の見た目で位置を調整するに越したことはありません。なので、実際の見た目でアイコン位置を調整してそのまま保存できるように、ゲームのプレイ中に自動レイアウトと保存ができるように仕様を変更することにしました。

f:id:negitoro113:20200325153631p:plain

できたものがこちら↑です。実際の見た目でレイアウトの保存・編集ができるようになりました。

実行中のゲームオブジェクトからエディタの機能を呼ぶのはUnityの仕様では基本的にできないのですが、Reflectionを使うなどして半ば無理矢理に実装しました。未経験の機能を使えて楽しかったです。

 

その他のタスク

上記のタスクを早めに終わらせることができたので、再びプログラマとプロデューサの方とミーティングして追加のタスクを決めました。不具合の修正や細かな改修をいくつか行いました。これらのタスクを通してコードの色々な箇所を見ることができ、勉強になりました!デバッグに思ったより時間がかかってしまったので、もっと効率的にデバッグができるようにならなければと反省しました…。

 

まとめ

靴を脱いで上がるオフィスや、リビングのような共有スペースがあり、非常に居心地のいいオフィスでした。また、一人一人の考えと行動で会社を良くしていくという文化が一貫していることが印象的でした。新しい事業や技術に挑戦している方も多くいらしゃいました。総じて、ストレスレスに楽しく働ける会社という印象を持ちました。

コロナの影響により多くの社員がリモートワークで会社にはいらっしゃらなかったですが、私の席の周りは結構人がいて寂しくはなく、それなりにコミュニケーションもとれたので良かったです。

今まで参加したインターンや仕事は、プロジェクトの立ち上げや開発初期段階のものがほとんどだったので、 既に数年サービスを継続しているプロジェクトで働いた経験は新鮮でとても勉強になりました。ありがとうございました!

脆弱性診断用に非ルート化端末でも動作するCUIのメモリ改ざんツール「apk-medit」を作った話

こんにちは、セキュリティエンジニアの小竹 泰一(aka tkmru)です。 アカツキでは、Webアプリケーション、ゲームアプリに対する脆弱性診断や社内ネットワークに対するペネトレーションテスト、ツール開発/検証などを担当しています。

メモリ改ざんによるチートとは

UI上に表示されている値を端末のメモリ上から検索し、見つけた値を改ざんすることでチートを行うことができる場合があります。 これはゲームのチート方法の中で最も簡単な方法で、脆弱性診断の際にも実際にメモリ上のデータを改ざんをすることでチートできるかどうか確認しています。 対策としては、XOR等を使ってメモリ上ではエンコードされた状態で値を保持し、UI上に表示されている値を検索されても見つからないようにする方法があります。

作ったツール

apk-meditという脆弱性診断のためのAndroidアプリ向けメモリ改ざんツールを作成しました。 CUIで動作し、非ルート化端末でも動作するのが特徴です。また、Goで実装しているため、Android NDKに依存していません。

github.com

使い方

非ルート化端末でメモリを読むためには、run-asコマンドを使い、実行しているアプリの権限でシェルを動作させる必要があります。 run-asコマンドはdebuggableなアプリにしか使えないため、対象のアプリがdebuggableでなかった場合には、 AndroidManifest.xmlを開きapplication nodeに対して、以下のattributeを追加する必要があります。

android:debuggable="true"

対象のアプリの準備ができたら、adbコマンドで/data/local/tmp/以下に実行バイナリをpushしてください。

$ adb push medit /data/local/tmp/medit
medit: 1 file pushed. 29.0 MB/s (3135769 bytes in 0.103s)

run-asコマンドの引数にターゲットのアプリのパッケージ名を指定し実行したあとは、自動的にディレクトリが変更されます。 apk-meditの実行バイナリを/data/local/tmp/からコピーして、実行してください。

$ adb shell
$ pm list packages # パッケージ名を確認
$ run-as <target-package-name>
$ cp /data/local/tmp/medit ./medit
$ ./medit

apk-meditを実行すると、インタラクティブなプロンプトが立ちがります。 プロンプト上に実装されたfindコマンドやpatchコマンドを用いて以下のようにメモリを改ざんすることができます。

f:id:TAKEmaru:20200327153009g:plain
apk-meditを使ってメモリ改ざんする様子
f:id:TAKEmaru:20200327153127g:plain:w175
メモリ改ざん対象のゲームの様子

フィルタ機能

小さく、キリがいい値はメモリ上にいくつもあり、1回の検索で目的のアドレスを見つけることは困難です。 そこで前回の検索で見つけたアドレスの中から、指定した値に変化しているアドレスを見つけるfilterコマンドを実装しました。

> find 100
Search UTF-8 String...
Target Value: 100([49 48 48])
Found: 712!
------------------------
Search Word...
Target Value: 100([100 0])
Found: 6605!
> filter 94
Check previous results of searching UTF-8 string...
Target Value: 94([57 52])
Found: 0!!!
------------------------
Check previous results of searching word...
Target Value: 94([94 0])
Found: 1!!!
Address: 0xe7021f70
> patch 5
Successfully patched!

filterコマンドを繰り返し使って見つかるアドレスを絞っていくことで、目的の値に到達することができます。

実装

ここでは、Goを使って開発することの利点は何なのか、 どのようにしてメモリ上のデータを読み込んでいるのかについて解説します。

開発にGoを使うメリット

今回の開発にあたり、Goを使って感じたメリットは以下の4つです。

  • ARM向けにバイナリを用意するのが簡単
  • システムコールの呼び出しが簡単
  • 大きいバイト列から目的のバイト列を高速に検索するのが簡単
  • GitHub ActionsとGoReleaserのおかげでバイナリを配布するのが簡単

ARM環境向けにLinuxバイナリを用意するのが簡単

Goコンパイラはクロスコンパイルをサポートしており、環境変数GOARCHGOARMにアーキテクチャ名とバージョンを、 環境変数GOOSにOS名を指定するだけでARM環境で動くLinuxバイナリを作成できます。

$ GOOS=linux GOARCH=arm64 GOARM=7 go build -o medit

システムコールの呼び出しが簡単

Golangにはシステムコールをいいかんじにラップしてくれているunixパッケージがあり、 システムコールを簡単に呼び出せます。 ptraceシステムコールを用いてプロセスへのアタッチするコードをC言語の場合と見比べてみましょう。

C言語でptraceシステムコールを用いたプロセスへアタッチは、<sys/ptrace.h>をインクルードすることで以下のコードでできます。 ptrace()の第3引数はcaddr_t addr, 第4引数はint dataとなっており、それぞれに読み出しや書き込みの対象とするメモリのアドレス、 書き込むデータを指定できるのですが、第1引数にPTRACE_ATTACHを設定したときは第3引数、第4引数がともに無視されます。 そのため、プロセスへアタッチする際にはそれぞれにNULLを指定する必要があります。

ptrace(PTRACE_ATTACH, pid, NULL, NULL);

Goではunixパッケージを使うと、以下のようなコードでptraceシステムコールを用いてプロセスへのアタッチができます。 Goでは不要な引数を指定しなくていいように、利便性を考えてシステムコールをラップしており、アタッチに使う関数の引数はひとつだけです。

sys.PtraceAttach(pid)

このようにGoではC言語を使うより簡単にシステムコールを扱うことができます。 Goにおけるシステムコールの扱いについては、少し古いsyscallパッケージを使ったものになりますが以下の記事が詳しいです。

ascii.jp

apk-meditでは動きが激しいアプリの動作を止めるために、ptraceシステムコールによるアタッチをattachコマンドを使ってできるようにしていますが、 メモリの読み込み、メモリへの書き込みにはptraceシステムコールを使っていません。 どのようにして、メモリ上のデータを検索しているのかは後ほど、解説します。

大きいバイト列から目的のバイト列を高速に検索するのが簡単

Rabin-Karp string search algorithmという高速に文字列を検索するアルゴリズムが bytes.Index()の内部で使われています。 これによって、複雑なアルゴリズムを自前で実装することなく、bytes.Index()を使うだけで高速にメモリ上のデータを検索することができました。

ja.wikipedia.org

GitHub ActionsとGoReleaserのおかげでバイナリを配布するのが簡単

これはGoの仕様によるものではなく、Goを使った開発を便利にしてくれるツールのおかげですが、 GoReleaserというGithub Releasesにバイナリを登録してくれるツールを、 GitHub Actions上で動かすことで、リリースバイナリを簡単に配布することができました。 以下のようなymlファイルを.github/workflows/以下に配置するだけで、GitHubにtag付きのコミットがアップロードされた際に、 GitHub Actions上でビルドが走り、GoReleaserがGithub Releasesにバイナリを登録してくれます。

name: release
on:
  push:
    tags:
    - "v[0-9]+.[0-9]+.[0-9]+"
jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v1
        with:
          fetch-depth: 1
      - name: Setup Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.14
      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v1
        with:
          version: latest
          args: release --rm-dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

どうやってメモリを読み込んでいるか

Linux系OSにおいて/proc/以下には、プロセスの情報にアクセスするための疑似ファイルが置かれています。 /proc/$pid/maps/proc/$pid/memを用いて、特定のプロセスのメモリマッピングを取得し、メモリを読み出す事が可能です。 /proc/$pid/mapsには以下のようなフォーマットでメモリマッピング情報が載っています。 ここには、pidで指定したプロセスがメモリのどの部分に書き込み権限、読み込み権限を持っているのかという情報が記載されています。

sargo:/data/data/jp.aktsk.tap1000000 $ cat /proc/11283/maps
12c00000-12d40000 rw-p 00000000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
12d40000-133c0000 ---p 00140000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
133c0000-13700000 ---p 007c0000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
13700000-13780000 rw-p 00b00000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
13780000-14140000 ---p 00b80000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
14140000-2ac00000 rw-p 01540000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
6f181000-6f3a6000 rw-p 00000000 fd:01 221            /data/dalvik-cache/arm/system@framework@boot.art
6f3a6000-6f3bc000 r--p 00225000 fd:01 221            /data/dalvik-cache/arm/system@framework@boot.art
6f3bc000-6f4b3000 rw-p 00000000 fd:01 229            /data/dalvik-cache/arm/system@framework@boot-core-libart.art
6f4b3000-6f4c5000 r--p 000f7000 fd:01 229            /data/dalvik-cache/arm/system@framework@boot-core-libart.art
6f4c5000-6f4f6000 rw-p 00000000 fd:01 232            /data/dalvik-cache/arm/system@framework@boot-conscrypt.art
6f4f6000-6f4f9000 r--p 00031000 fd:01 232            /data/dalvik-cache/arm/system@framework@boot-conscrypt.art
6f4f9000-6f526000 rw-p 00000000 fd:01 235            /data/dalvik-cache/arm/system@framework@boot-okhttp.art
6f526000-6f529000 r--p 0002d000 fd:01 235            /data/dalvik-cache/arm/system@framework@boot-okhttp.art
6f529000-6f57f000 rw-p 00000000 fd:01 240            /data/dalvik-cache/arm/system@framework@boot-bouncycastle.art
...

/proc/$pid/memを使って、pidで指定したプロセスが持つメモリを読むことができます。 よくある誤解として、ptraceシステムコールを使ってターゲットのプロセスにアタッチ(PTRACE_ATTACH)し、 プロセスを止めないとメモリを読めないというのがありますが、 最近のLinuxカーネルではアタッチしなくとも、システムコールのopen()、read()、lseek() を使ってメモリを読み出すことが可能です。 apk-meditでは、open()、read()、lseek()を直接は使っていませんが、 内部でそれぞれのシステムコールを使用しているio.NewSectionReaderFile.WriteAtを使って、読み込み、書き込みを行っています。 メモリマッピング情報から読み込み、書き込みが共にできる部分がどこなのかを得て、/proc/$pid/memを使ってメモリを読み出し、ターゲットの値を検索しています。

おわりに

apk-meditが脆弱性診断に従事するエンジニアに広く使われるよう育てていきたいと思っています。 ぜひ、気づいたことがあればフィードバックしてもらえるとうれしいです。みなさまからのIssueやプルリクエストをお待ちしております。

RSGT2020へのスポンサーをしました

f:id:yusi:20200131145917p:plain

アカツキとRSGT2020

アカツキでエンジニアリングマネージャをしている島村です。

去る2020年1月8−10日に「Regional Scrum Gathering Tokyo 2020」(以下 RSGT2020)が開催されましたが、昨年に引き続きスポンサーをさせていただきました!

Regional Scrum Gathering Tokyoとは

  • スクラムを実践する人が集い垣根を超えて語り合う場を提供するという目的によりコミットしています。

参加した方はわかると思いますが、通常のカンファレンスとは違い、Gatheringの名を示すように寄り合い所のような雰囲気が強くあり、セッションも深く考えさせられるようなものが多いです。

またセッション中に隣の人と語りあう時間をあえて用意するスピーカーもおり、そのような空気を一体となって作ってくれていました。
廊下やロビーのソファーなどで活発に意見交換がされているのも印象的でした。
まさに垣根を超えて語りあう場が形成されていたのです。

f:id:yusi:20200110121939j:plain
私達アカツキはこの理念に共感し2年連続でRSGT2020にスポンサーしています。*1

スポンサーをすることによりこのような素敵な場が毎年継続されればと思いますが、副次的にはRSGT2020に訪れる方々と出会い、さらに一緒に仕事ができるよう機会を得られればという面もあります。

参加してみて

筆者の私はというと1日目は丸々仕事で出れず、2日目も午前中は参加できませんでした。調整能力の低さを露呈してしまいお恥ずかしい限りです。

直接の参加はできなかったもののSNS上での盛り上がりは見ていました。

基調講演でのJames Coplien氏の「The Ten Bulls of the Scrum Patterns」の話は興味深く、スクラムと十牛図の語りには強く興味をもっています。
スクラムの本質を改めて考えさせられる場だったようで、参加できた同僚から改めて聞きたいと思います。

また二日目の基調講演のSahotaさんの「Lost in Translation: The Manager’s Role in Agile」も二日目の流れの源流になったとのことでSNS上で盛り上がっていました。
気になったワードは「ヒエラルキーをひっくり返す」「XY理論」「No One Gets Left Behind
一つ一つのキーワードが深く考えさせられるものです。

私は午後から参加したのですが、Sahotaさんからの流れのから組織変革とリーダーシップ、自立したチームとその価値観、マネージャの関わり方などのセッションが多くあり、一つ一つのセッションだけでなく、連続で聞いたときにより効果がでるようなセッションプログラムでした。
*2

いくつか印象的だったセッションの感想を。

キャッチーなタイトルなので興味本位で参加させてもらったが、会社単位でこの改革をしたことに脱帽です。

たしかにマトリクス組織よりチーム主体にしたときの方が小さく最適化はしやすいのは経験上あります。が、ここまで権限委譲をしたことはなく、チームがクリエイティブなところに集中できるようにマネージャ(部長)に権限と役割をもたせていました。「人員配置」や「予算」までも委譲することは考えたことがなかったです。

デメリットに1on1の実施が減っているということが記されていたので、やはり管理周りが弱くなる課題はあるようです。

また人材もチームや個人に裁量があり、体験入部制度で社内の流動性が高まる方向にあったようだが「メンバーの固定化」が弱くなることへの影響も気になりました。異動する個人を見ればモチベートにはなるので一長一短なのでしょう。

さらにマネージャ(部長)のチーム化した組織運営チームの例はとても興味深かく。職能の部長が本部全体を見るようになるので視座もあがりキャリア形成には良いかとおもいますが、「チームをまたがるところ」に課題があったようで、この組織運営チームがどこまで関与できるのか、上記の課題にどこまで関与できるのかポイントになってくるのでしょうか。

 チームで転職した及部さん(@TAKAKING22)の話しは興味があったので楽しみに参加しました。
冒頭から「チームの死とは」という疑問を会場に投げかけ、プロダクトに依存しない「Team-Based TEAM」を提唱していました。
ずっと会社員で働いてきた自分としては「会社・組織」「作るべきもの」が大前提で、それに最適化したチームやメンバー、作り方を考えることがあたり前という概念があり、プロジェクトが終われば「チームの解散(死)」は当たり前にくるものと思っていいて考えたことがなかったです。

タックマンモデルが、その通りに状態遷移するチームは2%であることが、改めてチームの継続は難しいこと考えさせられました。ただそれ以上にプロダクトが終わってもチームを死なせなかったこのチームの想いの強さには尊敬します。

また安定したチームにするには人材の固定ではなく、学習できるチームであることと説明があり、本質は「生物における新陳代謝をチームに実装する」入れていくとのこと。
チームで学習するというのはとても難しく様々な前提条件が必要になることもあるが、改めて自分のチームの一つの方向性を知ることができたのは大きいことでした。

 

他にも刺激的なセッションは多く、全体的には自分たちの組織とマネージャ、チームのあり方、またその中でどうやってチームで価値を創出していくかを考えさせられた1日でした。

最後に

f:id:yusi:20200203103505j:plain

アカツキでは、アカツキらしいプロジェクトマネジメント(≒チーム開発)を探求するメンバーの集まるコミュニティ four *3 があります。

今回のRSGT2020にはfourメンバーが多く参加し、現場に各々が持ち帰ってきており今後が楽しみです。
今年の開催中に発表された、来年のRSGT2021のチケットも既に多くのメンバーが購入済みの状態です。

ぜひ一緒にハートドリブンな世界を実現するエンジニアリングマネージャ、組織の成長、課題解決に取り組んでくれる仲間を募集しています。興味のある方はぜひ連絡をください。

hrmos.co

*1:2019年はシルバースポンサー、2020年はロゴスポンサーとなっています

*2:きっと運営の意図した流れだったのでしょう。熟練した運営はここまで考慮できることに驚きます。

*3:名前の由来は
1. 価値を出すために
2. 開発メンバーのために
3. アカツキのために
4. 自分たちのマネージメント力の強化のために
この4つの価値観を大切にするということからです。