たれながし.info

とあるITエンジニアの備忘録

Windowsのトースト通知を表示する方法

PowerShell/Pythonを使ってWindowsの「トースト通知」を表示する方法

目的

Windowsにはトースト通知という機能があります。
この記事では、PowerShellPythonでトースト通知を表示する方法を紹介します。

(Defenderがマルウェアを検知した時にモニター右下にピコーン!!て出るやつです。)

  ↓これ

PowerShellの場合

トースト通知はWindows Runtime API(WinRT API)として実装されているので、PowerShellから該当APIを呼び出す形になります。

トースト通知のひな型はXMLで定義します。XMLのサンプルはMicrosoftのサイトに記載があります。
ちなみに、XMLで画像を指定する時、絶対パスじゃないとダメっぽいです。(src='c:\test.png'の様に指定)

docs.microsoft.com

コード

シンプルな通知の例です。XML部分は別ファイルにすることも可能です。

$title = "タイトル"
$message = "メッセージ"
$detail = "詳細"

[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null

$app_id = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'

$content = @"
<?xml version="1.0" encoding="utf-8"?>
<toast>
    <visual>
        <binding template="ToastGeneric">
            <text>$($title)</text>
            <text>$($message)</text>
            <text>$($detail)</text>
        </binding>
    </visual>
</toast>
"@

$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
$xml.LoadXml($content)
$toast = New-Object Windows.UI.Notifications.ToastNotification $xml
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($app_id).Show($toast)

実行結果


Pythonの場合

Pythonを使ってトースト通知を表示するには、「Plyer」の「notification.notify」メソッドを使うのが簡単です。
「Plyer」も内部的には「WinRT API」を呼び出していると思います。

「Plyer」のソースコードGitHubで公開されています。
github.com

「notify」メソッドの仕様は、以下に記載があります。
(私のWindows10環境では、title, message以外の引数が動作することを確認できませんでした。)

plyer.readthedocs.io

コード

まず、pipで該当パッケージをインストールします。

pip install plyer


シンプルな通知の例です。

from plyer import notification
notification.notify(title = "タイトル", message="メッセージ")

実行結果

Azure SentinelにAzure ADのデータを接続する

Azure SentinelにAzure ADのデータを取り込むため、「データコネクタ」の設定をします。

はじめに

Azure SentinelにAzure ADのデータを取り込むため、「データコネクタ」の設定をします。

取り込めるデータ

計7種類のログが取りこめます。

  • サインインログ(対話型ユーザー サインイン ログ)
  • 対話型ではないユーザー サインイン ログ
  • サービス プリンシパルのサインイン ログ
  • マネージド ID サインイン ログ
  • AD FS サインイン ログ
  • 監査ログ
  • プロビジョニングログ

参考資料

下記を参考に作業しました。
docs.microsoft.com

作業実施

事前準備

Azure Sentinelは構築しておきます。
tarenagashi.hatenablog.jp


「サインインログ(対話型ユーザー サインイン ログ) 」の取り込みのみAzure AD Premium P1/P2ライセンスが必要です(有料ライセンス)。 ※その他についてはライセンス不要
f:id:tarenagashi_info:20210926013935p:plain

Azure ADに接続する

Azure SentinelをAzure ADに接続します。

Azure Sentinelの「データコネクタ」から「Azure Active Directory」を選択する
f:id:tarenagashi_info:20210926014131p:plain


取り込むログを有効にする
f:id:tarenagashi_info:20210926014303p:plain

動作確認

メニュー「ログ」に取り込まれたログ毎のテーブルが作成されます。
f:id:tarenagashi_info:20210926014423p:plain

  • 有効にした時間以降のログのみ取りこまれるようです。
  • ログ取り込みには10分程度の遅延があります。

個人的によく使うKQLのTips

Log Analyticsワークスペースから結果を取得する時に、個人的によく使うKQLのTipsとなります。
whereやextendなど、基本的なことは記載しません。

KQLで分からないことがあった場合、まず公式マニュアルを確認することをお勧めいたします。
Kusto 照会言語 (KQL) の概要 - Azure Data Explorer | Microsoft Learn

MS公式のチュートリアルもあります。
チュートリアル: 一般的なKusto 照会言語演算子について学習する - Azure Data Explorer | Microsoft Learn

期間指定

期間指定をする場合は「between演算子」を使います。
月の始めと終わりはstartofmonth関数、endofmonth関数で求めることができます。
同様の関数にstartofday関数、endofday関数などがあります。

let month = datetime(2021/09);
let start = startofmonth(month);
let end = endofmonth(month);
Table
| where TimeGenerated between(start..end)

UTCからJSTに変換

日時を表すdatetime型はUTC協定世界時)です。
JST日本標準時)に変換する方法はいくつかありますが、9時間足すと楽です(UTC+09:00)。
表示上は9時間足されている状態ですが、型としてはUTCなのでご注意ください。

let offset = 9h;
Table 
| extend Timestamp_JST = Timestamp + offset 

PowerShellを使ったCSVへのエクスポート

PowerShellInvoke-AzOperationalInsightsQuery」を使ってKQLクエリの結果をCSVファイルに出力できます。
定型業務の自動化に有効です。
tarenagashi.hatenablog.jp

ユーザー定義テーブルの作成

datatable演算子でテーブルを作成することができます。

let T = datatable(severity:string, value:long)
    ['High', 2, 'Medium', 1, 'Low', 0];

ユーザー定義関数

関数の作成が可能です。
「let [関数名] = (引数1: 型, 引数2: 型, ...){ 関数の中身 };」の様に記載します。

詳細は公式ドキュメントに記載があります。
ユーザー定義関数 - Azure Data Explorer | Microsoft Learn

テーブルを引数として渡すこともできますし、
以下のように引数にテーブル名を文字列で渡して、table()関数でテーブルを参照するといった使い方も可能です。

let func = (tableName: string){
    table(tableName)
    | where TimeGenerated > ago(7d)
    | summarize count()
};
let aadSignin = func("SigninLogs");
aadSignin

配列の使用

配列の作成

dynamic型」や「make_list()関数」を使うと配列を作成できます。

let nums = dynamic([1, 2]);
print(nums)

> [1,2]
let words = datatable(word:string)["New", "Ark"]
| summarize make_list(word);
words

> ["New", "Ark"]

配列の要素との比較

in演算子」を使って配列のいずれかの要素に等しい(※1)、「has_any演算子」を使って配列のいずれかの要素を含む(※2)といった判定ができます。
「==」「contains」「and」「or」を使っても書けますが、比較対象が多い場合は「配列」を使うことでシンプルに書けます。

※1:大文字、小文字を区別しない場合はin~演算子を使う
※2:すべての要素を含む判定は「has_all演算子」を使う

let nums = dynamic([1, 2]);
datatable(num:int)[0, 1, 2, 3]
| extend bool_ = num in (nums)

> |num|bool_|
  ===========
  |0  |false|
  |1  |true |
  |2  |true |
  |3  |false|
let words = datatable(word:string)["New", "Ark"]
| summarize make_list(word);
datatable(city:string)["New York", "London", "New Ark"]
| extend bool_ = city has_any (words)

> |city    |bool_|
  ================
  |New York|true |
  |London  |false|
  |New Ark |true |

テーブルの結合の種類について(結合フレーバー)

テーブルの結合に使うJoin演算子には「結合フレーバー(kind=xxx)」という、結合の種類を決めるパラメータがあります。

LeftTable
|join [kind=結合フレーバー] (RightTable) on column

「結合フレーバー」は全部で9種類あります。
公式マニュアルにベン図を使った説明があるので確認しておきましょう。
join 演算子 - Azure Data Explorer | Microsoft Learn

未指定の場合は「kind=innerunique(左側の重複を除去する内部結合)」が既定の動作となるので、都度指定した方が無難です。

ピボットテーブル

「ピボットプラグイン」により、ピボットテーブルの実現が可能です。
「ピボットプラグイン」の構文は「| evaluate pivot(引数)」になります。

詳細は公式サイトを確認してください。
pivot プラグイン - Azure Data Explorer | Microsoft Learn

<サンプルコード>
let InputTable = datatable(TimeGenerated:datetime, Item:string, Value:long)[
	datetime(2023/01/01), "項目_A", 1, datetime(2023/01/01), "項目_B", 2, 
	datetime(2023/01/01), "項目_A", 3, datetime(2023/01/02), "項目_B",4];
InputTable | evaluate pivot(Item, sum(Value), TimeGenerated)

<実行結果>
"TimeGenerated [UTC]","項目_A","項目_B"
"2023/1/1 0:00:00.000",4,2
"2023/1/2 0:00:00.000",0,4

外部データをテーブルとして利用

通常はログとして取り込んでいないデータ(インターネット上に公開されているデータや手元にあるデータなど)をクエリ内で参照して使いたい場合があると思います。
そういった場合に有効な方法です。

インターネットに公開されたCSVJSONファイルの利用

externaldata演算子」を使うと、インターネットに公開されたCSVJSONファイルをテーブルとして取り込んで利用することができます。
公開されたデータのURLを「externaldata演算子」の引数に指定することで取り込みを実施します。

externaldata(Columnname:columnType [, ...] )
	[storageConnectionString [, ...] ] [with(propertyName=propertyValue [, ...])]
CSVの場合

以下はインターネット上に公開されているCSVを読み込む例です。

let iocs = externaldata(DateAdded:string,FirstSeen:string,IoC:string,Type:string,TLP:string)
[@https://raw.githubusercontent.com/microsoft/mstic/master/Indicators/May21-NOBELIUM/May21NOBELIUMIoCs.csv] with (format="csv", ignoreFirstRecord=True);
iocs | where Type =~ "SHA256"| project IoC
JSONの場合

以下はインターネット上に公開されているJSONファイルを読み込む例です。

let azure_ranges = externaldata(changeNumber: string, cloud: string, values: dynamic)
    [https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20230828.json]
    with(format='multijson')
| mv-expand values
| mv-expand values.properties.addressPrefixes
| mv-expand values_properties_addressPrefixes
| summarize by tostring(values_properties_addressPrefixes);
azure_ranges

このクエリは、MSが公開するAzureのIPアドレスレンジが記載されたJSONファイルから、IPアドレスレンジを取得します。
この例で使用するJSONファイルは頻繁に更新されるため、動作確認を行う際は最新のファイル名「ServiceTags_Public_YYYYMMDD.json」を以下URLから確認してください。
https://www.microsoft.com/en-US/download/details.aspx?id=56519

「mv-expand演算子」は、テーブルの列要素が配列やプロパティバッグの場合に展開を行う演算子で、「make-list関数」「make-series関数」とは逆の動きとなります。
JSONはツリー構造なので、externaldata演算子で読み込んだ結果、必要な値が動的な要素に含まれる場合は「extend演算子」「mv-expand演算子」「summarize演算子」「distinct演算子」などを使って必要な情報を抽出する必要があります。

おまけ情報:SASの利用

externaldata演算子」はURLを指定してデータを取り込む形になるので、Azure Blob StorageにアップロードしたCSVJSONを参照することも可能です。
Azure Blob Storageには「SAS(Shared Access Signatures)」というアクセス制限機能があるので、インターネットにULしてもいいけどアクセス制限をしたいという場合に有効だと思います。

ウォッチリストの利用

インターネットに公開したくないけど外部データをテーブルとして使用したいという場合は「ウォッチリスト」が有効です。
ウォッチリスト」に格納した表形式のデータは「_GetWatchlist 関数」で参照することができます。

Azure Sentinelの環境構築

Azure Sentinelの構築手順

はじめに

検証目的でAzure Sentinelを構築したので、手順をメモします。
環境構築する手順だけ書きます。ログの取り込み設定は別途必要です。

参考にした資料

docs.microsoft.com

docs.microsoft.com

Azure Sentinelについて

Azure Sentinelは、Microsoftが提供するクラウド型のSIEM兼SOAR製品になります。

Microsoftが用意するクラウド上の環境にログを貯めて、そのログを分析してアラートを上げたり、アラートをトリガーにして何らかのアクションを起こしたり出来ます。
ログを分析するルールはMicrosoftが提供しているものもありますし、ユーザーが独自で定義することも可能です。

Azure SentinelはAzureのサービスの1つなので、使用するにはAzureのサブスクリプションが必要です。
以前は「Azure Sentinel」という名前でしたが、2021年11月に「Microsoft Sentinel」という名前になりました。

料金について

基本は下記3つの料金が掛かるみたいです。
Azure SentinelはLog Analyticsにデータを保持するので、その料金も掛かります。

  • Azure Sentinelの料金
    • Azure Sentinelの分析に掛かる料金、データ1GBあたり数100円程度
      最初31日は無料らしい
  • Log Analyticsの料金
    • ログデータのインジェスト
      • 取り込んだデータに対して掛かる料金、データ1GBあたり数100円程度
    • ログデータの保持
      • 取り込んだデータを保持する料金、データ1GB/月あたり10~20円前後
        Azure Sentinelが有効な場合90日は無料で保持できる

使う機能によっては、他の料金も掛かる。
例えば自動応答機能を使う場合、Azure Logic Appsの料金が掛かる。

構築手順

事前準備

Azure SentinelはAzureのサービスなので、Azureサブスクリプションが必要です。
f:id:tarenagashi_info:20210925145522p:plain

Azure Sentinelの構築

Azure Sentinelを構築します。掛かった時間は5分位でした。

新規にLog Analyticsワークスペースを作成する
※既存のワークスペースも利用可
f:id:tarenagashi_info:20210925145659p:plain


価格が安かったのでリージョンは「米国西部2」を選択しました。
※ログ送信元とリージョンが異なるとデータ転送に課金されるかも(料金 - 帯域幅 | Microsoft Azure
f:id:tarenagashi_info:20210925145723p:plain


作成したワークスペースにSentinelを追加する
f:id:tarenagashi_info:20210925150111p:plain


完了したらこの画面になります。
f:id:tarenagashi_info:20210925150142p:plain

データ保有期間の確認

Log Analyticsのデータ保有期間を確認しておきます。
初期設定は30日ですが、Azure Sentinelが有効な場合90日まで無料らしいので、変更しても良いかもしれない。
f:id:tarenagashi_info:20210925150227p:plain

Microsoft Defender for Endpoint APIを使ってみる

PowerShellREST APIでDefender for Endpointを操作してみる

はじめに

Microsoft Defender for Endpoint」には「Microsoft Defender for Endpoint API」というREST APIがあります。アラート一覧の取得や脆弱性一覧の取得など各種操作ができます。

今回はクライアントにPowerShellを使って、「Microsoft Defender for Endpoint API」を実行してみます。

参考資料

下記資料を参考にしました。

使用できる機能一覧が記載されています。
docs.microsoft.com

Powershellスクリプトサンプルが記載されています。
docs.microsoft.com

APIキーの取得

最初にAzure ADの「アプリの登録」から「APIキー」を取得します。

Azure ADの「アプリの登録」から「新規作成」をクリックする



「名前」を入力し「登録」



追加したアプリの情報「アプリケーションID」「テナントID」をメモしておく



APIのアクセス許可」 > 「アクセス許可の追加」 > 「所属する組織で使用しているAPI」 > 「WindowsDefenderATP」を検索しクリックする



アクセス許可を与える
※「Alert.Read.All」と「Vulnerability.Read.All」を許可した



「管理者の同意を与えます」をクリックする



「証明書とシークレット」から「新しいクライアントシークレット」から「追加」する



発行された「シークレット値」を認証で使用する


APIの実行

API実行の基本的な流れは下記となります。

  1. 認証の実施
    →認証トークンを取得
  2. APIの実行
    →認証トークンをHeaderに記載し、機能毎のURLにHTTP REQUESTを送信
  3. 結果の表示、保存

認証の実施

認証用のPowerShellスクリプトを作成します。

スクリプトを名前「Get-Token.ps1」で保存する
※メモした「テナントID」「アプリケーションID」「シークレット値」を記載する

# That code gets the App Context Token and save it to a file named "Latest-token.txt" under the current directory
# Paste below your Tenant ID, App ID and App Secret (App key).

$tenantId = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' ### Paste your tenant ID here
$appId = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' ### Paste your Application ID here
$appSecret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' ### Paste your Application secret here

$resourceAppIdUri = 'https://api.securitycenter.microsoft.com'
$oAuthUri = "https://login.microsoftonline.com/$TenantId/oauth2/token"
$authBody = [Ordered] @{
     resource = "$resourceAppIdUri"
     client_id = "$appId"
     client_secret = "$appSecret"
     grant_type = 'client_credentials'
}
$authResponse = Invoke-RestMethod -Method Post -Uri $oAuthUri -Body $authBody -ErrorAction Stop
$token = $authResponse.access_token
Out-File -FilePath "./Latest-token.txt" -InputObject $token
return $token



スクリプトを実行すると認証トークン(JWT形式)が取得できる ※取得から60分有効

powershell -ExecutionPolicy Bypass .\Get-Token.ps1



認証トークンは「https://jwt.ms」でデコードして、有効期限やアクセス許可など確認できる

  ...
  "exp": 1632390256,
  ...
  "roles": [
    "Alert.Read.All",
    "Vulnerability.Read.All"
  ],
  ...



APIの実行

下記ページを参考にAPI脆弱性一覧を取得してみます。
docs.microsoft.com


スクリプトを名前「Get-Vulnerabilities.ps1」で保存する

# 認証トークンの取得
$token = ./Get-Token.ps1

# HTTP Requestの送信先URL
$url = "https://api.securitycenter.microsoft.com/api/Vulnerabilities"

# HTTPヘッダ
$headers = @{ 
    'Content-Type' = 'application/json'
    Accept = 'application/json'
    Authorization = "Bearer $token"
}

# HTTP GETの送信
$response = Invoke-WebRequest -Method Get -Uri $url -Headers $headers -ErrorAction Stop

# 結果の出力
$response

$dateTimeForFileName = Get-Date -Format o | foreach {$_ -replace ":", "."}
$outputJsonPath = "./Vulnerabilities_$dateTimeForFileName.json"

$results = $response.Content
$results | Out-File -FilePath $outputJsonPath
$outputJsonPath



PowerShellで実行する

powershell -ExecutionPolicy Bypass .\Get-Vulnerabilities.ps1


結果の表示、保存

脆弱性一覧が、Responseの「Content」にJson形式で格納されている

StatusCode        : 200
StatusDescription : OK
Content           : {"@odata.context":"https://api.securitycenter.microsoft.com/api/$metadata#Vulnerabilities","value":
                    [{"id":"CVE-2021-37957","name":"CVE-2021-37957","description":"This vulnerability affects the follo
                    wi...
RawContent        : HTTP/1.1 200 OK
                    x-content-type-options: nosniff
                    x-request-id: 2739653b-0d05-4d78-862f-3f318e0d2ee6
                    OData-Version: 4.0
                    Strict-Transport-Security: max-age=31536000 ; includeSubDomains
                    Content-Lengt...
Forms             : {}
Headers           : {[x-content-type-options, nosniff], [x-request-id, 2739653b-0d05-4d78-862f-3f318e0d2ee6], [OData-Ve
                    rsion, 4.0], [Strict-Transport-Security, max-age=31536000 ; includeSubDomains]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : System.__ComObject
RawContentLength  : 5596077

./Vulnerabilities_2021-09-23T18.58.15.6747327+09.00.json



取得した脆弱性情報の先頭1つ目

{
	"@odata.context": "https://api.securitycenter.microsoft.com/api/$metadata#Vulnerabilities",
	"value": [
		{
			"id": "CVE-2021-37957",
			"name": "CVE-2021-37957",
			"description": "This vulnerability affects the following vendors: Google, Ubuntu, Debian. To view more details about this vulnerability please visit the vendor website.",
			"severity": "High",
			"cvssV3": 8.8,
			"exposedMachines": 1,
			"publishedOn": "2021-09-21T00:00:00Z",
			"updatedOn": "2021-09-22T00:00:00Z",
			"publicExploit": false,
			"exploitVerified": false,
			"exploitInKit": false,
			"exploitTypes": [],
			"exploitUris": []
		},

Azure AD登録したWindows10デバイスをIntuneに自動登録する

Azure AD登録したWindows10デバイスをIntuneに自動登録する

f:id:tarenagashi_info:20210923213651p:plain:w450

目的

前提

このページを見ると、IntuneにWindows10デバイスを登録する方法は沢山あります。
docs.microsoft.com

(Intune管理者が登録するとか、Intuneユーザーが登録するとか、Intuneにだけ登録するとか、AzureADに参加してIntuneに同期するとか、もう沢山の方法がある。)

目的

今回は、Azure ADに登録(Azure AD Registered)したWindows10をIntuneにも自動登録してみます。

f:id:tarenagashi_info:20210923213651p:plain:w450

※今回使用したWindows10デバイスはローカル認証しているので「Azure AD登録」としたが、企業などで利用しているオンプレADで認証しているWindows10デバイスの場合、「Hybrid Azure AD Join」にしてIntuneに自動登録することが多いのかなと思う。

参考にしたサイト

Microsoftの公開情報を元に作業しました。
docs.microsoft.com

バイス登録の実施

事前準備

ライセンスの入手

AzureAD PremiumとIntuneのライセンスが必要です。
今回はEMS E5の試用版ライセンスを取得して使用しました。
tarenagashi.hatenablog.jp

ライセンス割り当て

ユーザーに適宜ライセンスを割り当てる
f:id:tarenagashi_info:20210923134847p:plain:w600

Intune自動登録の有効化

Azure ADでWindows10デバイスのIntune自動登録を有効にします。

Azure ADの「モビリティ (MDM および MAM)」から「Microsoft Intune」を選択
f:id:tarenagashi_info:20210923135150p:plain:w600

MDMユーザースコープ」を「すべて」に変更し保存
f:id:tarenagashi_info:20210923135035p:plain:w600

Windows10デバイスのAzure AD登録

Windows10デバイスをAzure ADに登録します。

Windowns10デバイスの[設定] > [アカウント] > [職場または学校にアクセスする] > [接続]をクリックする
f:id:tarenagashi_info:20210923135229p:plain:w600

[電子メールアドレス]にAzure ADアカウントで認証する
※多要素認証が強制になってました
f:id:tarenagashi_info:20210923135339p:plain:w450

Windows HelloのPIN設定が表示されたので、今回はキャンセルしました。
f:id:tarenagashi_info:20210923135525p:plain:w450
f:id:tarenagashi_info:20210923135558p:plain:w450

職場アカウントまたは学校アカウントの追加完了
f:id:tarenagashi_info:20210923135747p:plain:w600

動作確認

Azure ADからデバイス登録されたことを確認する
※結合の種類が「Azure AD Registered」、MDMが「Microsoft Intune」となっている
f:id:tarenagashi_info:20210923140050p:plain:w600

Intune(https://endpoint.microsoft.com)にも登録されたことを確認する (表示されるまで10分位掛かる)
※Azure AD登録した端末なので、所有権が「個人」となっている
f:id:tarenagashi_info:20210923140259p:plain:w600

Enterprise Mobility + Security E5の試用版ライセンス取得してみた。

EMS E5の試用版ライセンスを取得してみた。

はじめに

Intuneを試用したくて、EMS E5の試用版ライセンスを取得したので手順をメモします。
既存のAzure ADテナントに追加する形で取得しました(ライセンス取得と同時にAzure ADテナントも作成する形ではない)。

ライセンス取得

Azure ADのライセンスメニューで「無料試用版を入手する」をクリック
f:id:tarenagashi_info:20210923053514p:plain:w600


EMS E5の「アクティブ化」をクリック
f:id:tarenagashi_info:20210923053640p:plain:w600


数秒で追加されました。250個もあります。
f:id:tarenagashi_info:20210923053808p:plain:w600

割り当てオプション

EMS E5で有効にできる機能一覧です。全部で9個あります。
f:id:tarenagashi_info:20210923053939p:plain:w600