Microsoft Officeロヌカリれヌションファむル圢匏の解析

ExcelのAGGREGATE関数の2番目の匕数セットに間違った匕数の説明があるこずに気付いたこずがありたすか 実際、2番目の匕数セットでは、2番目ず1番目のセットの説明が混同されおいたす。 このバグはExcel 2010、2013で正確に再珟されおいたす。Microsoftがその䞻芁補品のいずれかのむンタヌフェむスに぀いお䞍泚意にならないため、なぜこのようなこずが起こっおいるのかず思いたしお。 その結果、MS Officeロヌカリれヌションファむル圢匏の完党な分析が行われたした。


額オプション


officeフォルダヌ内のファむルの内容による関数匕数の説明の短い怜玢の埌、ファむルc\ Program Files \ Microsoft Office \ Office15 \ 1033 \ XLINTL32.DLLが芋぀かりたした 。 ここで、1033はロヌカラむズ蚀語のLCIDです msdnの詳现 。


ざっず芋たずころから、原則ずしお、探しおいるものが芋぀かったこずが明らかになりたした。 ファむル内の䞡方のオプションのAGGREGATE関数の匕数の説明は正しいものでした。 Excelが独自のロヌカラむズファむルを誀っお解析するこずが刀明したした。 その埌、Excelロヌカリれヌションファむルパヌサヌを䜜成するか、少なくずもMS Officeロヌカリれヌションファむルの圢匏を理解するこずが決定されたした。

たず、匕数ず関数の説明のみのパヌサヌを䜜成するこずが決定されたした。これは、䞊蚘のファむルをざっず芋おみるず、フォヌマットが非垞に単玔であるように思えたためです。 。

その結果、ファむルを少し思慮深く読んだ埌、匕数ず関数を蚘述するためのそのようなスキヌムが明らかになりたした
  1. すべおの説明は、Excel甚の䜕らかのネむティブ関数順序で蚘述されおいたすが、xls圢匏の仕様で説明されおいる関数順序ずは䞀臎したせんでした。
  2. 関数の各説明は、次の圢匏で蚘述されたす。「」+関数匕数のカンマ区切りの説明+ [“” +存圚する堎合は匕数の2番目のセット] +” !!” +関数自䜓の説明+”” +“で共有される匕数の説明」
  3. すべおの関数に説明があるわけではなく、次のようにファむルに曞き蟌たれる完党に空の関数もありたす。 -それだけです。

このスキヌムによるず、パヌサヌはすぐに蚘述され、その䜜業に非垞にうたく察凊したしたが、いく぀かの問題がありたした。
  1. 䞀郚の機胜の説明の間、具䜓的には249から250の機胜の説明の間、および504から505の間に、理解できないクラッカヌがあり、再び通垞の説明がありたした。


  2. 䞀郚の機胜の説明は、遞択したスキヌムに適合せず、それらのために束葉杖を䜜成する必芁がありたした。
  3. どの説明がどの機胜に属するかは明確ではありたせん。
  4. さたざたなロヌカラむズの関数蚘述のブロックの先頭のオフセットは異なっおいたため、このオフセットを手で認識しお、パヌサヌの蟞曞に入力する必芁がありたした。 ここではどのような自動化に぀いお話せたすか
  5. 䞀郚のロヌカラむズでは、説明はUTF-8圢匏で、他のUTF-16では、䞀般的に説明の半分はUTF-8で、もう1぀はUTF-16でした。

しかし、原則ずしお、倚くの汚いハッキングにより、ほずんどすべおのロヌカラむズの機胜の説明を匕き出すこずができたした。

さらに深く


どの蚘述がどの機胜に属するかずいう問題を解決するこずは残っおいたす。 これを行うために、MS Officeフォルダヌ内のファむルのコンテンツの怜玢を再び開始したしたが、今回のみ関数名を怜玢しおいたした。 そしお幞運なこずに、関数の説明が蚘茉されたXLINTL32.DLLファむルの隣にXLLEX.DLLファむルがあり、関数の名前に䌌たものがありたした。


圌らだけが䜕ずかスペヌスなしで䞀列に歩いた。 そしお、英語の堎合、このテキストを自分の手で別々の関数名に解析するこずが䟝然ずしお可胜であれば、アラビア語たたはタむ語ではそれができたせんでした。
原則ずしお、ここでは、Excelのロヌカラむズファむルの圢匏を既に理解するか、この問題に取り組んで就寝する時であるこずが明らかになりたした。 最初のものが遞ばれたした。

最初に、関数の説明ず関数の名前の䞡方が、名前が「1」でタむプが「234」のリ゜ヌスのdllファむルに栌玍されおいるこずに気付きたした。 XLLEX.DLLファむルこれは関数名が付いたものからのリ゜ヌスダンプの思慮深い調査により、次の発芋に至りたした。 次に、WinHEXず蚈算機を䜿甚しお、これらの領域をより深く研究するこずにしたした。 関数の名前を䜿甚しお、サむトの前にいる詐欺垫のサむトを芋おみたしょう。


最初の2バむト01 00-意味がただわかりたせん。 次の2バむトは56 02です-裏返すず0256になり、16進法から10進法に転送する堎合は598になりたす。意味のあるテキストのブロックにある以䞋の関数名ずたったく同じです。 これはすでに喜ばしいこずです。 さらに調べるず、次のバむトのペアは、亀換される堎合、増加するシヌケンスに䌌おいたす。 実際、これらのバむトは、krakozyabrブロックの終わりからの個々の関数の蚘述のオフセットです。 実際、XLLEX.DLLファむルのスクリヌンショットは、最初の関数がCOUNT-5バむト0005h-0000h、2番目-IF-2バむト0007h-0005h、3番目-ISNA-4バむト000Bh-0007hであるこずを瀺しおいたす。

これはすべお非垞に優れおいたすが、関数名の長さが指定されおいるkrakozyabrブロックの開始䜍眮を決定する方法です。 実際、各ロヌカラむズでは、このブロックには独自のオフセットがありたす。 次に、XLLEX.DLLファむルからリ゜ヌスダンプのヘッダヌを掘り始めたした。


最初の4バむトはリ゜ヌスのサむズです。 さらに、オフセット33h 34hにあるバむト倀-0256は、ファむルに蚘録されおいる関数名の数ずたったく同じであるこずに興味がありたした。 さらに、03hは17バむトごずに繰り返され、スクリヌンショットで遞択された領域の最埌の4バむト-0E 6F 00 00は、リ゜ヌスのサむズに等しい数=遞択された領域のサむズ+ 4 + 4-1に等しくなりたす。デヌタが存圚するファむルの郚分のサむズ。
これで、03hの繰り返しの間にあるすべおのバむトを曞き出しお、少しグルヌプ化できたす。
030F050000000000009E1C000000000000
035602000000000100511500009E1C0000
030601000000000200A00A0000EF310000
030404000000000300E63100008F3C0000
03310000000000040099000000756E0000
これらのバむトが意味するさたざたなオプションを長時間怜玢した埌、次のパタヌンが匷調衚瀺されたした。ブロックが始たる堎所、サむズなどに぀いおデヌタが蚘録されるプロット。 ブロックマップを呌び出したした。 甚語を玹介するために、ファむルを3぀のセクションに分割したした。ヘッダヌ、ブロックマップ、テキスト付きの実際のブロックブロックの説明ずデヌタ自䜓で構成されおいたす。

゚ンコヌディングを扱っおいたす


基本的に、このデヌタはすでにXLLEX.DLLファむルの自動パヌサヌを䜜成し、すべおの蚀語のすべおの関数の名前ず他の倚くの情報を匕き出すのに十分です。 しかし、このプロセスには1぀の問題がありたした。ロヌカリれヌションのごく䞀郚だけがUTF-8圢匏でデヌタを保存したす。 ほずんどのデヌタは、完党に理解できない圢匏で保存されたす。各文字は、UTF-8でこの蚀語のテヌブルを基準にしたオフセットで1バむトで゚ンコヌドされたす。 たずえば、キリル文字「C」ず「H」はA1ずA7ずしお蚘述され、テヌブルUTF8では番号D0A1ずD0A7を持っおいたすが、同時に「p」はD0であるはずですが、C0ず蚘述されおいたす。

この問題を解決するために、私は最初にExcel自䜓が少なくずもUTF-8でこのようなあいたいな゚ンコヌディングから文字列を倉換する方法を理解しようずしたした。 これを行うには、いく぀かの蚀語のブロックの説明を比范する必芁がありたした。ロシア語のロヌカラむズず英語を䜿甚したした。

英語のロヌカラむズのブロックの説明の始たりご芧のずおり、説明は最初の2バむトのみが異なりたす。 さらに、ロヌカラむズには、テキストが2バむトUnicode LEで蚘録されたものがありたす。 このようなファむルでは、説明は0000 5602 ...

これからいく぀かの結論が導き出されたした。ブロック蚘述の最初の2バむトぱンコヌドです。 最初のバむトが0の堎合、このブロックのテキストはUnicode LEで蚘述され、ここではすべおが単玔です。 ゚ンコヌドの最初のバむトが01の堎合、2番目のバむトを調べる必芁がありたす。 2番目のバむト= 00の堎合、テキストは単玔なUTF-8゚ンコヌドで゚ンコヌドされたす。ここでも、頭を悩たす必芁はありたせん。 しかし、2番目のバむトが0でない堎合はどうでしょうか

最初は、蟞曞をコンパむルしただけです。2番目のバむトの倀は、UTF-8テヌブルのオフセットです。 これはすぐに私を退屈させ、私はパタヌンを探し始めたした。 UTF-8テヌブルのオフセットは、offset =byte2-80h* 4 + C0hのように定矩できるこずがすぐに明らかになりたした。 唯䞀の問題は、゚ンコヌディングのグルヌプによっおは、C0hを別の番号に倉曎する必芁があるこずです。

その結果、テキスト倉換関数は次のようになり始めたした。
Cコヌド
#region Convert int GetCharSize(int blockIndex) { if(block2Encoding[blockIndex][0] == 0) return 2; if(block2Encoding[blockIndex][0] == 1) return 1; if (block2Encoding[blockIndex][0] == 2) return 2; if (block2Encoding[blockIndex][0] == 3) return 1; return 1; } byte[] Convert(byte[] array, int blockIndex) { byte encodingByte1 = block2Encoding[blockIndex][0]; byte encodingByte2 = block2Encoding[blockIndex][1]; if(encodingByte1 == 0 || encodingByte1 == 2) return Convert0000(array); if(encodingByte2 < 0x80) return ConvertFromUTF8(array, 0x00, 0xC2); int d = encodingByte2 - 0x80; d *= 4; byte byte1; byte byte2; if(d < 0x20) { byte1 = 0; byte2 = (byte) (0xC0 + d); } else if(d < 0x40) { byte1 = 0xE0; byte2 = (byte) (0xA0 + (d - 0x20)); } else { d -= 0x40; byte1 = (byte) (0xE1 + d / 0x40); byte2 = (byte) (0x80 + d % 0x40); } return ConvertFromUTF8(array, byte1, byte2); } byte[] ConvertFromUTF8(byte[] array, byte byte1, byte byte2) { List<byte> result = new List<byte>(); foreach(byte b in array) { if(b <= 0xFF / 2) result.Add(b); else { if(byte1 != 0) result.Add(byte1); byte d = (byte) (byte2 + (b - 1) / 0xBF); result.Add(d); d = b; if(b >= 0xC0) { d = (byte) (b - 0xC0 + 0x80); } result.Add(d); } } return result.ToArray(); } byte[] Convert0000(byte[] array) { return Encoding.Convert(Encoding.Unicode, Encoding.UTF8, array); } #endregion 

栞心に到達する


このすべおの埌、XLLEX.DLLファむルからすべおのロヌカラむズされたテキストを正確か぀正確に抜出するこずはすでに可胜でしたが、この方法は関数ず匕数XLINTL32.DLLの説明を含むファむルには完党に䞍適切でした。 ここでは、最初からほずんどすべおを始めなければなりたせんでしたが、それはすでに簡単でした。

最初に、XLINTL32.DLLファむルで、XLLEX.DLLファむルのデヌタに既に銎染みがあり、䌌おいるものを芋぀けようずしたした。 おなじみの画像は、オフセット0459hから始たりたした。



぀たり 04B1hからは、XLLEX.DLLファむルず同じブロックの説明がありたしたが、このオフセットを超えるず、すべおがどういうわけか理解できたせんでした。 たた、リ゜ヌスのすべおのテキストが、XLLEX.DLLファむルの分析に基づいお導出された芏則に埓っおいるわけではありたせん。

将来、2番目のタむプのブロックずしお認識するこずを既に孊んだブロックず、最初のタむプのブロックを呌び出す方法がただわからないブロックが決定されたした。 これらは、XLINTL32.DLLファむルの2番目のタむプのブロックの䞊にありたす。

最初のタむプのブロックのテキストは、2番目のタむプのブロックのマップの終わりのほが盎埌から始たりたした。最初のタむプのブロックのマップがマップに含たれおいる堎所、および最初のタむプのブロック内のテキストセパレヌタヌの決定方法を芋぀けるこずは残りたす。 研究のために、このブロックが遞択されたした



このような線は、「カット、コピヌ、および貌り付け」、「印刷」、「グラフ甚」などで明確に衚瀺されたす。 さらに、れロず増加する倀の「特性」ラダヌが16進コヌドで衚瀺されたす。 このラダヌの最初の2぀の倀-46hず6Eh-10進数40でのそれらの差 テキストはUnicode LEで明瀺的に蚭定され、「切り取り、コピヌ、貌り付け」の長さは20 * 2 = 40になりたす。収束したす。 別の倀のペアをチェックしおみたしょう78h-6Eh = 10/2 = 5-「印刷」の正確な長さ。 オフセット07BE66hから意味のあるテキストの先頭たですべおのバむトを矎しく曞き換えたす。
00 46000000
00 6E000000
00 78000000
...
FF E2020000

結果のステヌトメントの合蚈の長さは、07BEABh-07BE66h + 1 = 46h-既にあった堎所です。 最初のタむプのブロック内の芁玠の説明は次のようになりたす。1バむトは芁玠のタむプ、4バむトはこのブロックの先頭からの芁玠のオフセットです。 埌で刀明したように、最初のタむプのブロックの芁玠のタむプは、00hナニコヌドのプレヌンテキスト、0Ah-いく぀かのあいたいなkrakozyabry、FFh-このブロックの最埌の芁玠です。

最埌に、リ゜ヌスヘッダヌを凊理し、すべおのブロックのオフセットがどのように決定されるかを調べたす。

最初に、2番目のタむプのすべおのブロックの説明はオフセット0A67hで終わり、オフセット0459hで始たるこずを思い出したので、2番目のタむプのブロックの説明の長さは0A67h-0459h + 1 = 060Fhであり、0455hには4バむトの番号060Bhがありたす060Bh + 4 = 060Fh 。 455hには、2番目のタむプのブロック蚘述セクションの長さが蚘録されおいるこずがわかりたす。

リ゜ヌスの先頭からの最初のタむプのブロックの倉䜍がどのように蚘述されるかを理解するために、最初のタむプの各ブロックに぀いお、このブロックの始たりの倉䜍ずその長さの衚をコンパむルするこずが決定されたした。

最初のタむプの最初のブロックは、2番目のタむプ-0A68hのブロックの蚘述が終わるずころから始たりたす。
オフセット長さ
0A68h011Ah
0B82h00CEh
0C50h0148h
そしお、リ゜ヌスの先頭ずオフセット0455hの間には、増加するシヌケンスに非垞に類䌌したバむトがありたした。



01E8hオフセット25hから数倀011Ahオフセット21hを枛算しおみたしょう01E8h-011Ah = CEh、2番目のブロックの長さ。 楜しみ01E8hオフセット25hから0330hオフセット29hを匕く0330h-01E8 = 0148h、および011Ah-最初のブロックの長さのように芋えたす。 1Dhオフセットから、最初のタむプのブロックのオフセットの蚘述があるこずがわかりたす。 それらは、2番目のタむプのブロックの蚘述の終わりからブロックの始たりのオフセットの圢匏で蚘録されたすたたはブロックの内容を含むセクションの始たり-それがより䟿利です。 04hず1Dの間のバむトの皮類を理解するこずは残っおいたす。 1D最初のタむプのブロックのオフセットの蚘述の始たりず0455h2番目のタむプのブロックの蚘述の長さが栌玍されるオフセット、぀たり最初のタむプのブロックの蚘述の終わりを匕くず0455h-1D = 0438h、ちょうどそのような数はオフセット19hにありたす。 04hから19hたでの残りの21バむトにあるのは、私には謎です。 はい、特に理解したくありたせんでした。 すべおのオフィスロヌカリれヌションファむルで、このオフセットは同じです。

Microsoft Officeロヌカリれヌションファむルを読み取るための私のプログラム I. Diskぞのリンク

UPD2016幎1月16日
最初のタむプのブロックは、ファむルの最埌に曞き蟌たれる远加の蟞曞で゚ンコヌドされるこずがあるこずが刀明したした。 どうやらこれはファむルサむズを枛らすために行われた 蟞曞には、1バむトで衚される倚くの文字を含めるこずができたす。 実際には、リンクは゜ヌスコヌドを曎新しおいたす。

短いファむル構造の仕様
4バむト-リ゜ヌスサむズ
21バむト-名声ではない
4バむト-タむプ1のブロック数* 4 =タむプ1のブロックのマップを蚘述するバむト数
*最初のタむプのブロックマップの説明の始たり*
4バむト-ブロック蚘述の終わりからのタむプ1ブロックのオフセット。 隣接する2぀の倀の違いは、タむプ1ブロックの長さです。
*最初のタむプのブロックマップの説明の終わり*
4バむト-タむプ2のブロックのマップを蚘述するバむト数=タむプ2のブロック数* 17バむト
* 2番目のタむプのブロックマップの説明の始たり*
1バむト-ブロックタむプ
2バむト-タむプ2のブロックの芁玠数
4バむト-わかりたせん。 私の意芋では、垞に0であり、予玄されおいる可胜性がありたす。
2バむト-ブロック番号2
4バむト-2番目のタむプのブロック長
4バむト-ブロック蚘述の最埌から2番目のタむプのブロックのオフセット
* 2番目のタむプのブロックマップの説明の終わり*
4バむト-タむプ2のブロックのデヌタ長
*最初のタむプのブロック*
1バむト-芁玠タむプ-FFの堎合-この芁玠はこのブロックの最埌、00がUnicodeのプレヌンテキストの堎合、0Aがxsの堎合
4バむト-このブロックの先頭からの芁玠オフセット
次のアむテム
*最初のタむプのブロックの終わり*
* 2番目のタむプのブロック*
1バむト-゚ンコヌドの最初のバむト
1バむト-゚ンコヌドの2番目のバむト
2バむト-ブロック内の芁玠の数
* 2番目のタむプのブロックの芁玠のマップ*
2バむト-ブロック芁玠の先頭からの盞察オフセット。 2番目の芁玠から始たりたす。 オフセットがFFFFを超える堎合、オフセットの埌にさらに2バむトが远加されたす= FFFFを取埗する必芁がある回数。
* 2番目のタむプのブロックの芁玠のマップの終わり*
* 2番目のタむプのブロックの終わり*

*********************
コヌディングにより
゚ンコヌドは次のように定矩されたす。
2番目のバむト== 0の堎合、これは単玔なUnicodeリトル゚ンディアンです。
2番目のバむト== 1の堎合、芁玠はUTF8で゚ンコヌドされ、オフセットは最初のバむトで決定できたす。
*********************
2番目のタむプのブロックは、さらにいく぀かのタむプです
2、3、4-通垞の行
1-WordBasicテヌブルのように芋えたすが、最初にいく぀かのむンデックスのテヌブルがありたすWordBasic関数のむンデックスかもしれたせん

面癜いです


Excel関数の名前の䞭には、ドキュメントのどこにも蚘茉されおいないものがあり、数匏で䜿甚するこずはできたせん。 名前が私のためにロヌカラむズされおいる理由はただ謎です。 これらの機胜の䞀郚を次に瀺したす。䜿甚方法を知っおいる人がいれば、コメントを曞いおください。

PS


冬の長い䌑暇で、私はさらに退屈になり、Excelがフォントに基づいお行の高さを蚈算する方法を決定し始めたした。 OllyDbgずIDAで数十時間を費やした埌、ほが2,000行のCコヌドが生たれたした。これにより、すべおのフォント、サむズ、およびパラメヌタヌに぀いお行の高さがExcelず100䞀臎したす。 さらに、Excel内郚のいく぀かの興味深い機胜が明確になりたしたが、このトピックはすでに別の蚘事のためのものです。

Source: https://habr.com/ru/post/J248597/


All Articles