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

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

アカツキでフルリモートインターンをしました

こんにちは!

この度クライアントエンジニアとしてインターンシップで勤務させていただきました、堀越と申します。

本記事では、インターンシップ期間 (2020年9月1日〜9月18日) 中に取り組んだこと、感じたことなどを書いていきます。アカツキのことを知りたい方、これからインターンシップを受けようと考えている方などの手助けになれば幸いです。

インターンシップへ参加した経緯

まずは、インターンへ参加した経緯をお話ししたいと思います。

就活を考え始める季節、春。

ということで、今年の5月に開催された逆求人イベントに参加し、そこで、アカツキさんとお話ししました。

自分としては、就職するのであれば自分が楽しめることを積極的にできる職場がいいということが一番にあったので、そういったようなビジョンを掲げていたアカツキさんに興味を持ちました。

そして、そういったことを自身で感じるために、自身の持っているスキルで参加できるインターンとして、参加させていただくことにしました。

インターンシップで取り組んだこと

さて、上記の理由でインターンに参加したわけですが、次に具体的にインターンで何をしたのかをお話ししたいと思います。

今回インターンとして関わらせていただいたのは、アカツキを代表するスマホゲーム『八月のシンデレラナイン』です。個人的に高校時代の思い出が蘇ってきてなんとも言えない気持ちになるゲームです。

f:id:toshiyuki_horikoshi:20200918184929p:plain

そこでは、自分はクライアントエンジニアとしてインターンに参加しました。

業務内容としては、クライアントサイドの機能改修です。

以下にインターン中に主に取り組んだことを紹介していきます。

次ステージへの自動遷移

まずは、次ステージへの自動遷移を実装しました。

現状、ステージをクリアした際に、ステージがアンロックされる場合はそのステージに遷移するようになっています。しかし、ステージを攻略している際にいちいちステージのアイコンをタップするのは面倒です。

そこで、ステージをクリアした後に、挑戦できるステージがある場合には自動で挑戦する直前の画面まで遷移する機能をつけることで、ユーザーの負担を減らす仕組みを実装しました。

f:id:toshiyuki_horikoshi:20200918191656p:plain

強化時のボイスをプロフィールボイスからシーンボイスへと変更

次に、強化時のボイスをプロフィールボイスからシーンボイスへと変更しました。

ハチナイには、様々な選手がいるのはご存知かと思います。また、それぞれの選手でもシーンごとで再生されるボイスが違うということも知られているでしょう。これまで、選手シーンを強化する際には、再生されるボイスは別々のシーンでも同一の選手であれば同じボイスが再生されていました。

今回は諸々の理由で、製品版にはこの変更を含めないことになりましたが、開発段階ではシーンごとに再生されるボイスを変更することによって、そのシーンの背景だったり、情景だったりがより感じられるようになったのではないかと思っていました。

デレストでデレストのオーダーを参照して音声が再生されるようにする

現在、デレストで練習メニューを実行する際に、デレストオーダーに含まれていない選手のボイスが再生されることがありました。

これを、デレストオーダーに含まれている選手と、一緒に練習する選手のボイスのみが流れるようにすることによって、違和感なくデレストを行えるように変更しました。 

インターンシップで感じたこと

今回のインターンシップはフルリモートということもあって、実際にアカツキという会社の雰囲気を知りたくてインターンシップに参加した自分にとっては少し残念ではありましたが、実際に業務に関わる上で、とても貴重な経験をさせていただきました。

また、他のインターンシップ生や今回の業務では関わることのなかった社員の方とリモートではありますが交流をする機会を数多くいただきました。

リモートで業務に携わることについて、自分自身多少なりとも不安に感じることはあったのですが、メンターの方や同じチームの方と協力をすることによってタスクをこなす際に特にそれらのことが障壁となるようなことありませんでした。

業務を行う面でも、社員の方と関わってアカツキのことを知るという面でも自分にとってはとても有意義なインターンになったかと思います。

最後に

短い期間ではありましたが、アカツキという会社を実際に業務に携わることでより深く知ることができたと感じています。

また、実際にリリースされているアプリケーションの改修をするにあたって、まだまだ自分の至らないことなど、多くを学ばせていただきました。

本当にありがとうございました。

CloudFormationでAuroraのMySQL5.7インプレースアップグレードをする際のハマりポイント&対応方法

Amazon Aurora MySQL のインプレースアップグレード機能

つい先日、Amazon Aurora にて、MySQL 5.6互換のバージョン1.xから、MySQL 5.7互換のバージョン2.xへインプレースアップデートが可能になりました。

Amazon Aurora が MySQL 5.6 から 5.7 へのインプレースアップグレードをサポート

この機能を使うことで、従来のようにスナップショットからの復元やレプリケーション、インスタンスの切替といった作業をしなくても、エンドポイントなどはそのままに、簡単にMySQL5.7互換にアップグレードすることが可能になります。

早速この機能でアップグレードを試みたのですが、CloudFormationで管理されているAuroraクラスターをアップグレードする際にちょっとハマったことがあったので、その内容と対応方法をシェアします。

アップデート前のRDS用CloudFormation stack

更新前のDBクラスタのCloudFormationでの定義はこんな感じでした。(わかりやすいよう最小限の記述のみにしてあります)

DevAuroraParameterGroup というカスタムのインスタンスパラメータグループを使っています。

---
AWSTemplateFormatVersion: '2010-09-09'
Description: RDS for sandbox
Resources:
  DevAuroraParameterGroup:
    Type: AWS::RDS::DBParameterGroup
    Properties:
      Description: Development Aurora parameter group
      Family: aurora5.6
      Parameters:
        max_connections: '1024'
        wait_timeout: '300'
  DevAuroraParameterGroup57:
    Type: AWS::RDS::DBParameterGroup
    Properties:
      Description: Development Aurora parameter group for 5.7
      Family: aurora-mysql5.7
      Parameters:
        max_connections: '1024'
        wait_timeout: '300'
  DBCluster:
    Type: AWS::RDS::DBCluster
    Properties:
      DBClusterIdentifier: test-cluster
      DBSubnetGroupName:
        Fn::ImportValue: DBSubnetGroup
      Engine: aurora
      EngineVersion: 5.6.mysql_aurora.1.22.2
      MasterUsername: "{{resolve:ssm:rds.username.default:1}}"
      MasterUserPassword: "{{resolve:ssm-secure:rds.password.default:1}}"
  DBInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Delete
    Properties:
      DBClusterIdentifier:
        Ref: DBCluster
      DBInstanceClass: db.t2.medium
      DBInstanceIdentifier: test-db
      Engine: aurora
      EngineVersion: 5.6.mysql_aurora.1.22.2
      DBParameterGroupName:
        Ref: DevAuroraParameterGroup
      DBSubnetGroupName:
        Fn::ImportValue: DBSubnetGroup

ハマったこと

これを、以下のように書き換えて適用することで、MySQL5.7互換バージョンへのインプレースアップグレードを試みます。

@@ -82,8 +82,8 @@
       DBClusterIdentifier: test-cluster
       DBSubnetGroupName:
         Fn::ImportValue: DBSubnetGroup
-      Engine: aurora
-      EngineVersion: 5.6.mysql_aurora.1.22.2
+      Engine: aurora-mysql
+      EngineVersion: 5.7.mysql_aurora.2.07.3
       MasterUsername: "{{resolve:ssm:rds.username.default:1}}"
       MasterUserPassword: "{{resolve:ssm-secure:rds.password.default:2}}"
   DBInstance:
@@ -94,9 +94,9 @@
         Ref: DBCluster
       DBInstanceClass: db.t2.medium
       DBInstanceIdentifier: test-db
-      Engine: aurora
-      EngineVersion: 5.6.mysql_aurora.1.22.2
+      Engine: aurora-mysql
+      EngineVersion: 5.7.mysql_aurora.2.07.3
       DBParameterGroupName:
-        Ref: DevAuroraParameterGroup
+        Ref: DevAuroraParameterGroup57
       DBSubnetGroupName:
         Fn::ImportValue: DBSubnetGroup

しかし、以下のようなエラーで失敗してしまいました。

{
  "LogicalResourceId": "DBCluster",
  "ResourceStatus": "UPDATE_FAILED",
  "ResourceStatusReason": "The current DB instance parameter
     group sandbox-rds-devauroraparametergroup-fxfe7dqcn31p
     is custom. You must explicitly specify a new DB instance
     parameter group, either default or custom, for the engine
     version upgrade. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterCombination; Request ID: ...)"
}

カスタムのインスタンスパラメータグループを使っているため、5.7に対応した新しい DevAuroraParameterGroup57 に切り替えるよう指定しなければなりません。 CLIであれば modify-db-cluster--db-instance-parameter-group-name オプションでこれを指定可能です。 しかし、どうやらCloudFormationではこれを渡すことができない様子です。同時に DBInstance の更新をしても、異なるリソースの変更までは拾ってはくれないようです。。

対応方法その1

こういう時の一つの方法は、いったんCloudFormationの管理下から外してしまい、手動でアップデートしたのち、CloudFormationにインポートし直すという方法です。

  1. DBCluster および DBInstanceDeletionPolicy: Retain を指定して適用することで、CloudFormationによってこれらが削除されないようにします。

  2. DBCluster および DBInstance の定義を削除し、更新を行います。

  3. 残ったクラスターをAWSコンソールで5.7に更新します。

  4. 5.7の定義で再度 DBCluster および DBInstance の定義を追加し、「インポート」 を行います。この時、追加する各リソースに対応するインスタンスの識別子(ここでは test-clustertest-db )を指定することで、CloudFormationスタックに既存リソースを取り込むことが可能です。

  5. ドリフト検知を行い、定義と実態にズレがないことを確認します。

しかし、手動オペレーションはなるべく避けたいということで、次のような方法も考えてみました。

対応方法その2

エラーメッセージを見るに、カスタムのインスタンスパラメータグループを使わなければ良いのだろうということで、いったんデフォルトに戻し、インブレースアップグレード後に再びカスタムのパラメータを適用しなおしてみます。

まず、 DBInstance のパラメータグループをデフォルトである default.aurora5.6 にしてスタックを更新します。

@@ -96,7 +96,6 @@
       DBInstanceIdentifier: test-db
       Engine: aurora
       EngineVersion: 5.6.mysql_aurora.1.22.2
-      DBParameterGroupName:
-        Ref: DevAuroraParameterGroup
+      DBParameterGroupName: default.aurora5.6
       DBSubnetGroupName:
         Fn::ImportValue: DBSubnetGroup

次に、 インプレースアップグレードと合わせて、新しいカスタムのパラメータグループも指定して再度更新します。

@@ -82,8 +82,8 @@
       DBClusterIdentifier: test-cluster
       DBSubnetGroupName:
         Fn::ImportValue: DBSubnetGroup
-      Engine: aurora
-      EngineVersion: 5.6.mysql_aurora.1.22.2
+      Engine: aurora-mysql
+      EngineVersion: 5.7.mysql_aurora.2.07.3
       MasterUsername: "{{resolve:ssm:rds.username.default:1}}"
       MasterUserPassword: "{{resolve:ssm-secure:rds.password.default:2}}"
   DBInstance:
@@ -94,8 +94,9 @@
         Ref: DBCluster
       DBInstanceClass: db.t2.medium
       DBInstanceIdentifier: test-db
-      Engine: aurora
-      EngineVersion: 5.6.mysql_aurora.1.22.2
-      DBParameterGroupName: default.aurora5.6
+      Engine: aurora-mysql
+      EngineVersion: 5.7.mysql_aurora.2.07.3
+      DBParameterGroupName:
+        Ref: DevAuroraParameterGroup57
       DBSubnetGroupName:
         Fn::ImportValue: DBSubnetGroup

これで、無事にCloudFormationのみでインプレースアップグレードが完了しました。 またMySQL5.7への移行完了後も、DBは問題なく利用できることを確認できました。

後者の方法は途中でパラメータグループの更新が余分に入るという欠点がありますが、対象が多くて自動化したい場合などはこちらの手段の方が良いこともあるかもしれません。

もっとうまく対応できる方法が提供されるとありがたいのですけれどね。

モバイルで動くShaderでの流体表現


この記事は Akatsuki Advent Calendar 2020の25日目の記事です.
前回の記事は脆弱性診断時のAndroidのプロキシ設定を行うコマンドラインツールを作った話+その他内製ツールの紹介でした。

 

 

はじめに


新卒研修で流体を用いたスマホゲームをリリースする機会がありましたので,実装を紹介します.

具体的には,ミラーケーキ(ケーキの一種)を作成するゲーム内で,
ケーキに溶けたチョコをかけてコーティングする作業(グラサージュ)の実装です.

(実際のアプリ: iOS, Android

実際の動画


実際のゲームプレイ動画がこちらになります.この部分の実装方法を以下で説明していきます.

f:id:AxI:20201223125005g:plain
ちなみに実際のミラーケーキはこんな感じです.

実装

概要:ケーキの柄が変わってるだけ

モバイルで三次元流体表現を行うことはスペック上難しいので,二次元で液体挙動の近似計算を行い,影で立体感をつけることで上記の挙動を実現しています.
具体的には,ケーキオブジェクトのテクスチャをリアルタイムで変化させることで,ケーキの表面に液体が流れているかのように見せています.

f:id:AxI:20201224123839p:plain
ぱっと見,ケーキになにか物体が覆いかぶさっていくように見えますが,実はケーキの柄が変わっているだけです.

実装は主に3つのパートに分かれています.以下の処理はUnity×Shaderで実装されています.
1.液体の広がりを表現
2.液体の流れを表現
3.液体の立体感を表現

液体の広がり


液体の広がりでは,ミラーケーキでのグラサージュの特徴である,注いだ点からじわーっと広がる挙動を表現しています.

具体的には二次元上で液量を定義し,”ぼかし”(平滑化)を行うことで液体が多いところから少ないところへ広がる動きを計算しています.毎フレームShader上で周囲のピクセルの液量の平均をそのピクセルの次の値とすることで,下図のように注いだ点から周囲に広がり,付近の液量と影響しあう挙動となります.

f:id:AxI:20201223133432p:plain

上図において,液量2以上など,閾値以上の部分のみ液体が存在すると定義し,液体が存在するところは別のテクスチャを参照するとすることで下図のようになります.

f:id:AxI:20201223133450p:plain

液体の流れ


液体の流れでは,液体が流れていく方向へ色も移動する処理を行います.

先ほどの液体の広がりで用いた図を見ると,液体範囲の縁は閾値に近くなることがわかります.よって,閾値に近い部分に黄色をつけるとするならば,黄色は常に外側,つまり液体が流れていく方向へ移動することになります.
このように液量が似ているピクセルは似た色を参照するという仕組みにすることで,流れていく方向に色が移動しているような挙動になります.

f:id:AxI:20201223133505p:plain
具体的には,液体範囲が液体テクスチャを参照する際,テクスチャの参照座標を液量分ずらすことで,任意のテクスチャにおいて液量に伴い変動するマーブル模様が生成され.流体っぽい挙動を実現しています.(時間が経つと戻っていく など,実際の流体挙動とは大きく異なる部分があります)

f:id:AxI:20201223133516p:plain

液体の立体感


液体の立体感は,液体の広がりで計算された,液体が存在する範囲の周囲に影をつけることで表現されています.
具体的には,テクスチャ上で光の方向を定義し,液体が存在しない かつ 光の逆向きに隣接するピクセルに液体が存在するピクセルを黒くします.

f:id:AxI:20201223133532p:plain

f:id:AxI:20201223133542p:plain

影をつけることで一気に立体感が出たと思います.影と反対側にハイライトをつけることでより立体感,艶感がでます.
上記の三つの要素を合体させることでモバイルで動く流体表現を実装しました.

おわりに


実際のアプリリンクです.楽しんでいただけたら幸いです.

Mirror cakes - Apps on Google Play

Mirror cakes on the App Store

 

限定的な状況下の実装ですがみなさまの発想の助けになれば幸いです.
来年も,おもしろいがたくさん生まれますように,メリークリスマス.

 

【LT会】Akatsuki Geek Live 2020-2021 開催レポート!Vol.1

こんにちは!アカツキ採用担当のこさだです。

12/14(月)に、本年度1回目となる「Akatsuki Geek Live2020-2021 Vol.1」を開催しました!この状況下ですので、初の完全オンライン実施となりましたが、50名以上の方にご参加をいただき、とても良い場になりました!今回は、そのイベント当日の様子をご紹介したいと思います!

 

「Akatsuki Geek Live」とは?

エンジニアを志す学生さんと、アカツキエンジニアが登壇するLT会です。フリーテーマで7分間のLTを実施、その後懇親会を実施し、交流の場を設けています。楽しみながらアカツキのことを知れる場、そして学生さん同士の横のつながりも作れる場として実施しております。

 

▼イベント概要はこちらから

aktsk.connpass.com

 

 #当日の様子

今回は完全オンラインでの開催となりました。昨年まではアカツキオフィスに実際にお越しいただいての開催だったため、少し不安もありましたが、当日は50名を超える方にご参加いただきました!

はじめに採用担当のまえだからスタートし、アカツキのエンジニア3名、来春入社予定の内定者2名、一般学生1名の計7名が登壇。
登壇者から資料掲載の承諾をいただきましたので、下記にスライドをご紹介します!

 

▼@まえださん(アカツキ/採用担当)

なるほどよくわかる!アカツキ理解のヒント 

トップバッターはエンジニアの採用を担当しているまえださんから。
アカツキを知るにはどうしたらいいか?や学生のみなさんがなかなか聞きづらいポイントを解説しました!

 【登壇資料】

 

▼@になさん(アカツキ/17年度新卒入社)

Unity の CI 環境をGithub Actions で構築した話

エンジニアトップバッターはになさん。
なぜやるか?「やってみたかったから」というのが正直でいいですよね!
問題意識をもったこと、やりたいと思う方法をやってみる。「ワクワクして働く」ということを体現している一つの例かもしれませんね。

【登壇資料】

 

▼@Bapliscaさん(一般学生)

「ボイストラベラー」サークルで新感覚ボイスゲームを作った話
学祭で制作した音声認識でUFOを操るゲームについて発表していただきました。
「あ〜〜〜⤴︎⤴︎あ〜⤵︎⤵︎ ・・・ビーム!!!!」とデモも披露していただき、笑いが巻き起こり、チャットも盛り上がる時間でした(個人的にも画面越しにめちゃくちゃ笑いました)
アセットを使わずに制作したとのことで、様々な工夫が素晴らしかったです。
「子供が操作しやすいゲームを作りたい」という目的が達成されていて、とても素晴らしいと思いました!遊んでみたい!(888888)

【登壇資料】

 

▼@なかじさん(学生/21年度新卒内定)

DOTweenはいいぞ

来年、アカツキへの入社を決めてくれている21卒内定者のなかじさんです。
ゲームを開発されている学生の皆さんから「DOTween使ってみたい!」という声がチャットから溢れてきていました!
【登壇資料】

 

▼@いたみんさん(アカツキ/19年度新卒入社)

研修でゲームをリリースした話

入社後の研修で作ったゲームの話でした。毎年少しずつ研修内容は変わるのですが、入社直後の研修で作ったゲームをすぐリリース!というのはなかなか実施されている企業は多くないのではないでしょうか。作ってみて初めてわかる難しさ、「感覚的に楽しくできる」にたどり着くまでは色々な苦労があるんですよね。

【登壇資料】

 

▼@すぎやんさん(学生/21年度新卒内定)

競プロと業プロの関係性について

なかじさんと同じく、内定者のすぎやんさん。
就職活動で感じた違和感と、何から初めていいかわからないという思いから、「競プロ」を始めてよかったぞ!という話をしてくれました。
面接での自己アピールの伝え方を変えてみることや、自分でもサービスを作ってみることで自分にも変化があったとのこと。視点を変えて考えてみるというのは本当に大事!

【登壇資料】

 

▼@ちょうさん(アカツキ/19年度新卒入社)

RailsのN+1あるある

アカツキで実際の業務で使っているRuby on Railsdでの例をもとに、わかりやすく解説してくれました!当日司会をしていた島村と同じチームということもあり、先輩後輩による掛け合いも面白かったですねw

【登壇資料】

 

 

#LTを経て懇親会!
オンラインでの開催でしたが、チャットで盛り上げてくださる学生の皆さんのおかげもあり、発表者も楽しくLT登壇を終えられました。その空気感のままオンライン懇親会へ。
なんだかまるでラジオの公開収録をみているような雰囲気でしたね!皆さんからチャットで投稿される質問に答えていきながら、アカツキの業務やコロナ禍リモートでの業務について、登壇者へ向けての質問など様々な話題が時間いっぱいまで活発に飛び交っていました。アカツキの雰囲気も伝わる有意義な時間になったのではないでしょうか?
オフィスで直接みなさんにお会いできなかったのは残念でしたが、ご来社いただける状況が戻ってきた時には、ぜひ遊びに来てくださいね^^
 

改めて、ご参加いただいた皆さま本当にありがとうございました!この時間ががみなさんのエンジニアとしての気付きや新たな1歩、また良き出会いの場になっていれば嬉しいです!

 

最後にオフショットを★(広〜い空間で、こんな風にお届けしておりました)

f:id:megumikosada:20201221093503j:plain

次回は2月頃に開催できたらいいな、と思っています!ぜひまた会いましょう〜!

メリークリスマス!!

脆弱性診断時のAndroidのプロキシ設定を行うコマンドラインツールを作った話+その他内製ツールの紹介

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

今日は、先日作成したAndroidのプロキシ設定をコマンドラインから行うツールの紹介と、その他にもある脆弱性診断に使える内製ツールの紹介をします。 この記事は、Akatsuki Advent Calendar 2020の24日目の記事です。

脆弱性診断に使うプロキシツールとは

脆弱性を発見する方法のひとつに、対象となるWebアプリ、スマホアプリの通信内容をプロキシツール上で確認し、リクエストやレスポンスを編集するという方法があります。 脆弱性診断時に用いるプロキシツールは、Burp SuiteやPacketProxyなどが知られています。

f:id:TAKEmaru:20201217044534p:plain
中間者攻撃を行う様子

スマホアプリの通信をプロキシツールへと向ける方法

スマホアプリの通信をプロキシツール上で確認するには、端末のネットワーク設定を変更しプロキシツールへと通信を曲げる必要があります。 ここではよく用いられる2つの方法を紹介します。

プロキシのIPアドレス、ポートを指定

プロキシツールが動作しているPCのIPアドレス、ポートを端末のネットワーク設定画面で指定することでプロキシツールへと通信を向けることができます。 これは最も簡単な方法です。

Androidでは、Wi-Fiの詳細設定から、プロキシのIPアドレス、ポートを指定可能です。iOSを使用している場合も設定する項目は同じです。

Android上でプロキシを設定する画面

DNSサーバーを追加し、レコードを偽装する

PacketProxyには自由にDNSレコードを変更できるDNSサーバーが組み込まれています。 このDNSサーバー上でアプリの通信先のドメインを指定し、プロキシツールを経由して通信するようにDNSレコードを偽装することで、通信内容を取得できます。 この方法は、指定したドメインとの通信のみを取得できる点や、SSL Pinningが施されていても通信先のドメインを確認することができる点で便利です。

Androidでは、プロキシのIPアドレスを指定する場合と同じくWi-Fiの詳細設定画面から、DNSの設定を変更可能です。 ここで指定するDNSサーバーのIPアドレスはPacketProxyが動作しているPCのアドレスです。 Androidの場合は、次の画像のように端末のIPアドレス、ゲートウェイのIPアドレス、ネットワークプレフィックス長も指定する必要があります。 iOSの場合はDNSのアドレスを差し替えるだけでOKです。

Android上でDNSサーバーを設定する画面

コマンドラインからプロキシの設定を行えるツールを作成した

プロキシの設定をGUIを操作して行うのは少し手間がかかります。 特にAndroidでDNSサーバーを指定するには、DHCPをオフにして端末のIPアドレス等も指定しないといけないのでめんどくさいです。 そのため、コマンドラインからプロキシの設定を簡単に行えるよう、aprox を作成しました。

github.com

インストール方法

aproxはPythonで作成されているため、pipでインストール可能です。

$ pip install git+ssh://git@github.com/aktsk/aprox.git

使い方

サブコマンドを指定することで、機能を呼び出せます。

プロキシを指定する

proxyコマンドでプロキシが待ち受けているIPアドレス、ポートを設定できます。

$ aprox proxy 192.168.100.10:8080
Local proxy has been set up

DNSサーバーを指定する(root化端末限定)

dnsコマンドでDNSサーバーのIPアドレスを指定できます。 この機能はroot権限が必要なndcコマンドを使っているため、root化端末をPCにつないでいる場合しか使えません。

$ aprox dns 192.168.100.10
200 0 Resolver command succeeded

設定をクリアする

clearコマンドでプロキシ、DNSサーバの設定をクリアできます。

$ aprox clear
Local proxy is not configured...
Cleared local DNS settings!!

開発時に知ったデバッグテクニック

ndcコマンドに関してはあまりドキュメントがなく、扱いに苦戦しました。そのため、DNSのリクエストが本当に端末から出ているのか確かめたくなりました。 ちなみにaproxの内部では次のようにndcコマンドを使って、DNSサーバーを追加しています。

$ su
# dumpsys netd # 現在の使用しているネットワークIDを確認
# ndc resolver setnetdns <ネットワークID> '' <IP アドレス> 

DNSのログは次のように確認できました。 iptablesコマンドを使い、ログの先頭にDNS_QUERIESという文字列を追加し、dmesgコマンドでログを確認しています。

3|sargo:/ $ su
sargo:/ # iptables -I OUTPUT -m udp -p udp --dport 53 -j LOG --log-prefix 'DNS_QUERIES '
sargo:/ # dmesg -w | grep 'DNS_QUERIES'
[54672.362220] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=192.168.100.15 LEN=59 TOS=0x00 PREC=0x00 TTL=64 ID=40850 DF PROTO=UDP SPT=41015 DPT=53 LEN=39 MARK=0xf0068 
[54672.525921] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=106.187.2.33 LEN=59 TOS=0x00 PREC=0x00 TTL=64 ID=50180 DF PROTO=UDP SPT=55042 DPT=53 LEN=39 MARK=0xc0068 
[54672.526507] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=106.187.2.33 LEN=59 TOS=0x00 PREC=0x00 TTL=64 ID=50181 DF PROTO=UDP SPT=26049 DPT=53 LEN=39 MARK=0xc0068 
[54672.589872] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=192.168.100.15 LEN=59 TOS=0x00 PREC=0x00 TTL=64 ID=40865 DF PROTO=UDP SPT=42598 DPT=53 LEN=39 MARK=0xf0068 
[54672.847426] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=106.187.2.33 LEN=67 TOS=0x00 PREC=0x00 TTL=64 ID=50221 DF PROTO=UDP SPT=33378 DPT=53 LEN=47 MARK=0xc0068 
[54672.848117] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=106.187.2.33 LEN=67 TOS=0x00 PREC=0x00 TTL=64 ID=50222 DF PROTO=UDP SPT=31970 DPT=53 LEN=47 MARK=0xc0068 
[54672.849920] DNS_QUERIES IN= OUT=wlan0 SRC=192.168.100.20 DST=106.187.2.33 LEN=63 TOS=0x00 PREC=0x00 TTL=64 ID=50223 DF PROTO=UDP SPT=50412 DPT=53 LEN=43 MARK=0xc0068

また、このようにログを確認することで、アプリから出るDNSのリクエストの宛先は指定したものに変更されているが、ブラウザから出るDNSのリクエストの宛先はデフォルトのままであることが分かりました。 アプリの脆弱性診断では現状のままで困らないので、このまま公開しています。

他の内製診断ツール

アカツキでは、他にも脆弱性診断時に使えるツールを作成し、OSSとして公開しています。

apk-medit

apk-meditは、root権限を必要としないメモリ改ざんツールです。 メモリ改ざんはスマホゲームの脆弱性診断時に見る項目のひとつです。 このツールに関しては、Black Hat USA Arsenalや、CODE BLUE Blueboxなどで発表しました。

github.com

以前にも社のブログに紹介記事を書いたので、興味があればこちらも読んで見てください!

hackerslab.aktsk.jp

apkutil

apkutilは、APKファイルをデコードする際にandroidmanifest.xmlをパースし様々な情報を表示したり、脆弱性診断に必要なパッチを自動で当てたりしてくれるツールです。

github.com

次のようにコマンドを実行することで、debuggable属性をtrueにしたり、networkSecurityConfigの設定をしたりしつつ、再度ビルドしてくれます。

$ apkutil all sample.apk
Decoding APK by Apktool...
I: Using Apktool 2.4.1 on sample.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
...

Potentially Sensitive Files:
sample/README.md
sample/hoge.sh

Checking AndroidManifest.xml...
Permission:
android.permission.INTERNET

Debuggable:
False

AllowBackup:
False

Custom schemas:
None

Set debuggable attribute to true in AndroidManifest!

Set networkSecurityConfig attribute to true in AndroidManifest!

Building APK by Apktool...
I: Using Apktool 2.4.1
I: Checking whether sources has changed...
...

Signing APK by apksigner...
Signed

Output: sample.patched.apk

上で挙げたapk-meditはdebuggable属性がtrueになっているアプリを前提に作られているので、apk-meditを使う際にはとても便利です。

ipautil

ipautilは、IPAファイルをデコードする際にInfo.plistをパースし様々な情報を表示したり、センシティブなファイルがないか確認したりしてくれるツールです。

github.com

次のようにコマンドを実行することで、IPAファイルをデコードできます。

$ ipautil decode sample.ipa
Decoding IPA...
Archive: sample.ipa
   creating: Payload/
   creating: Payload/demo-client iOS develop.app/
   creating: Payload/demo-client iOS develop.app/_CodeSignature/
  inflating: Payload/demo-client iOS develop.app/_CodeSignature/CodeResources  
  inflating: Payload/demo-client iOS develop.app/demo-client iOS develop  
...
  inflating: Payload/demo-client iOS develop.app/Info.plist  

CFBundleName:
demo-client iOS develop

CFBundleDisplayName:
demo-dev

Checking AppTransportSecurity...
True

NSExceptionDomains:
facebook.com

Custom schemas (CFBundleURLSchemes):
None

Potentially Sensitive Files:
./Payload/demo-client iOS develop.app/README.md
./Payload/demo-client iOS develop.app/hoge.sh

Output: ./Payload

また、IPAファイルはパッチ当てた後、リザインしないとインストールできませんが、リザインは結構手間です。 ~/ipautil.jsonに証明書の情報を書いておくことで、コマンド1発でリザインする機能もあります。

$ ipautil sign Payload/
Signing IPA by codesign...
Payload/demo-client iOS develop.app/Frameworks/Hoge.framework: replacing existing signature
Payload/demo-client iOS develop.app/Frameworks/Fuga.framework: replacing existing signature
Payload/demo-client iOS develop.app: replacing existing signature
Signed

NWPentestUtils

NWPentestUtilsは、内部ネットワークでのペネトレーションテスト業務で使用しているスクリプト集です。

github.com

DBサーバーを指定したネットワークレンジから見つけるfind-db.shやブルートフォース攻撃を行うbruteforce-postgres.shbruteforce-mysql.shbruteforce-redis.shあたりは特にお気に入りです。

$ ./find-db.sh target-ip.txt 
Target: 192.168.100.0/24
172.16.0.0/12
Now Launching: nmap -p3306 -v -oX results/20201221/192.168.100.0_24_mysql_20201221_140057.xml 192.168.100.0/24
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-21 14:00 JST
Initiating Ping Scan at 14:00
Scanning 512 hosts [2 ports/host]
...
Read data files from: /usr/local/bin/../share/nmap
Nmap done: 512 IP addresses (9 hosts up) scanned in 34.01 seconds
Now Launching: nmap -p5432 -v -oX results/20201221/192.168.100.0_24_postgre_20201221_140131.xml 192.168.100.0/24
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-21 14:01 JST
Initiating Ping Scan at 14:01
Scanning 512 hosts [2 ports/host]
Completed Ping Scan at 14:01, 14.59s elapsed (512 total hosts)
Initiating Parallel DNS resolution of 9 hosts. at 14:01
Completed Parallel DNS resolution of 9 hosts. at 14:01, 11.03s elapsed
...

DBサーバーにログインできた場合、RCEにまで持ち込めるケースがあります。

hackerslab.aktsk.jp

また、Nmapが出力したXMLファイルをスプレッドシートにコピーしやすいようCSV形式に変換するnmap-xml2csv.rbは地味に便利です。

$ ruby nmap-xml2csv.rb ./results/20201204/192.168.1.0_24_20201204_072122.xml
[+] parse these xml files:
./results/20201204/192.168.1.0_24_20201204_072122.xml
-----------------------------------------------------
192.168.1.1 53(domain), 80(http)
192.168.1.17    22(ssh)
-----------------------------------------------------
[+] Output: portscan-result.csv

おわりに

aproxという最近作成したツールの紹介と、今までに作成したツールの紹介をしました。 アカツキのセキュリティチームでは脆弱性診断をただ単に行うだけではなく、効率よく行うためのツールの作成も積極的に行い、OSSとして公開することで業界に貢献していく姿勢をとっています。

一緒に脆弱性診断やツール開発を行いたい方は、ぜひ採用ページから応募してください。お待ちしています。

hrmos.co