সমাধান 1: সি (ম্যাক ওএস এক্স x86_64), 109 বাইট
Golf_sol1.c এর উত্স
main[]={142510920,2336753547,3505849471,284148040,2370322315,2314740852,1351437506,1208291319,914962059,195};
উপরোক্ত প্রোগ্রামটি____ ডেটা বিভাগে এক্সিকিউশন অ্যাক্সেসের সাথে সংকলন করা দরকার।
clang golf_sol1.c -o golf_sol1 -Xlinker -segprot -Xlinker __DATA -Xlinker rwx -Xlinker rwx
তারপরে প্রোগ্রামটি চালনার জন্য নিম্নলিখিতটি চালান:
./golf_sol1 $(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')
ফলাফল:
দুর্ভাগ্যক্রমে ভালগ্র্যান্ড সিস্টেম কলগুলি থেকে বরাদ্দকৃত মেমরির জন্য নজর রাখে না, তাই আমি একটি ভাল সনাক্ত হওয়া ফুটোটি দেখতে পাচ্ছি না।
তবে আমরা বরাদ্দ মেমরির বৃহত্তর অংশটি দেখতে (ম্যালোক মেটাডেটা) ভিএমএ্যাপে দেখতে পারি।
VIRTUAL REGION
REGION TYPE SIZE COUNT (non-coalesced)
=========== ======= =======
Kernel Alloc Once 4K 2
MALLOC guard page 16K 4
MALLOC metadata 16.2M 7
MALLOC_SMALL 8192K 2 see MALLOC ZONE table below
MALLOC_TINY 1024K 2 see MALLOC ZONE table below
STACK GUARD 56.0M 2
Stack 8192K 3
VM_ALLOCATE (reserved) 520K 3 reserved VM address space (unallocated)
__DATA 684K 42
__LINKEDIT 70.8M 4
__TEXT 5960K 44
shared memory 8K 3
=========== ======= =======
TOTAL 167.0M 106
TOTAL, minus reserved VM space 166.5M 106
ব্যাখ্যা
সুতরাং আমি মনে করি উন্নত সমাধানের দিকে যাওয়ার আগে আমার এখানে আসলে কী চলছে তা বর্ণনা করা দরকার।
এই মূল ফাংশনটি সি এর অনুপস্থিত প্রকারের ঘোষণাকে অপব্যবহার করছে (সুতরাং এটি লেখার অক্ষরগুলি নষ্ট করার প্রয়োজন ছাড়াই আমাদের পূর্বনির্ধারিত হয়), পাশাপাশি কীভাবে চিহ্নগুলি কাজ করে। লিঙ্কারটি কেবলমাত্র mainকল করার জন্য ডাকা প্রতীকটি খুঁজে পাবে কিনা তা নিয়ে চিন্তা করে। সুতরাং এখানে আমরা int এর মূল একটি অ্যারে তৈরি করছি যা আমরা আমাদের শেলকোড দিয়ে শুরু করব যা কার্যকর হবে। এ কারণে, প্রধানটিকে __TEXT বিভাগে যুক্ত করা হবে না বরং __Data বিভাগে যুক্ত করা হবে, কারণ আমাদের একটি নির্বাহযোগ্য __Data বিভাগের সাথে প্রোগ্রামটি সংকলন করতে হবে।
মূলত পাওয়া শেলকোডটি নিম্নলিখিত:
movq 8(%rsi), %rdi
movl (%rdi), %eax
movq 4(%rdi), %rdi
notl %eax
shrq $16, %rdi
movl (%rdi), %edi
leaq -0x8(%rsp), %rsi
movl %eax, %edx
leaq -9(%rax), %r10
syscall
movq (%rsi), %rsi
movl %esi, (%rsi)
ret
এটি যা করছে তা মেমরির একটি পৃষ্ঠা বরাদ্দ করার জন্য সিস্কল ফাংশনটিকে কল করছে (সিস্কেল ম্যাক_ভিএম_লোকট অভ্যন্তরীণভাবে ব্যবহার করে)। আরএক্স 0x100000a এর সমান হওয়া উচিত (আমরা কী ফাংশনটি সিস্কেলকে বলি), যখন আরডিআই বরাদ্দের লক্ষ্য রাখে (আমাদের ক্ষেত্রে আমরা এটি ম্যাচ_টাস্ক_সেলফ হতে চাই)), নতুন তৈরি হওয়া স্মৃতিতে পয়েন্টার লেখার জন্য আরএসআইয়ের ঠিকানাটি রাখা উচিত (সুতরাং আমরা এটি কেবল স্ট্যাকের একটি অংশের দিকে নির্দেশ করছি), আরডিএক্স বরাদ্দটির আকার ধারণ করে (আমরা কেবল বাইটস সংরক্ষণ করতে কেবল RAX বা 0x100000a এ যাচ্ছি), আর 10 পতাকা ধারণ করে (আমরা এটি ইঙ্গিত করছি যে এটি করতে পারে) যে কোনও জায়গায় বরাদ্দ করা হবে)।
এখন এটি স্পষ্টভাবে সুস্পষ্ট নয় যে আরএক্স এবং আরডিআই তাদের মানগুলি কোথা থেকে পাচ্ছে। আমরা জানি RAX এর 0x100000a হওয়া দরকার, এবং আরডিআই-এর মান ম্যাক_টাস্ক_সেলফ () হওয়া উচিত। ভাগ্যক্রমে mach_task_self () আসলে একটি ভেরিয়েবলের জন্য ম্যাক্রো (mach_task_self_), যা প্রতিবার একই মেমরি ঠিকানায় হয় (তবে পুনরায় বুট করা উচিত)। আমার বিশেষ উদাহরণে mach_task_self_ 0x00007fff7d578244 এ অবস্থিত। সুতরাং নির্দেশাবলী কাটাতে, আমরা পরিবর্তে এই তথ্যটি আরজিভি থেকে পাস করব। এই কারণেই আমরা এই অভিব্যক্তিটি দিয়ে প্রোগ্রামটি পরিচালনা করি$(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')প্রথম যুক্তি জন্য। স্ট্রিংটি দুটি মান সম্মিলিত, যেখানে RAX মান (0x100000a) কেবলমাত্র 32 টি বিট এবং এতে একটির পরিপূরক প্রয়োগ করা হয়েছে (সুতরাং কোনও নাল বাইট নেই; মূলটি পাওয়ার জন্য আমরা কেবল মানটি পাই না), পরের মানটি আরডিআই (0x00007fff7d578244) যা শেষে 2 টি অতিরিক্ত জাঙ্ক বাইট যুক্ত করে বামে স্থানান্তরিত হয়েছে (নাল বাইটগুলি বাদ দিতে, আমরা কেবল এটি আসলটিতে ফিরে পেতে ডানদিকে ফিরে স্থানান্তরিত করব)।
সিস্কেলের পরে আমরা আমাদের নতুন বরাদ্দ মেমরিটিতে লিখছি। এর কারণ হ'ল ম্যাক_ভিএম_লোকট (বা এই সিসকল) ব্যবহার করে বরাদ্দ করা মেমরিটি আসলে ভিএম পৃষ্ঠাগুলি, এবং মেমরিতে স্বয়ংক্রিয়ভাবে পৃষ্ঠাযুক্ত হয় না। বরং এগুলি সংরক্ষণ করা হয় যতক্ষণ না তাদের কাছে ডেটা লেখা হয় এবং তারপরে সেই পৃষ্ঠাগুলিকে মেমরিতে ম্যাপ করা হয়। নিশ্চিত ছিল না যে এটি প্রয়োজনীয়তাগুলি কেবলমাত্র সংরক্ষিত থাকলে পূরণ করবে কিনা।
পরবর্তী সমাধানের জন্য আমরা আমাদের শেলকোডের কোনও নাল বাইট নেই বলে সুবিধা গ্রহণ করব এবং এর ফলে আকার হ্রাস করার জন্য এটি আমাদের প্রোগ্রামের কোডের বাইরে নিয়ে যেতে পারে।
সমাধান 2: সি (ম্যাক ওএস এক্স x86_64), 44 বাইট
Golf_sol2.c এর উত্স
main[]={141986632,10937,1032669184,2,42227};
উপরোক্ত প্রোগ্রামটি____ ডেটা বিভাগে এক্সিকিউশন অ্যাক্সেসের সাথে সংকলন করা দরকার।
clang golf_sol2.c -o golf_sol2 -Xlinker -segprot -Xlinker __DATA -Xlinker rwx -Xlinker rwx
তারপরে প্রোগ্রামটি চালনার জন্য নিম্নলিখিতটি চালান:
./golf_sol2 $(ruby -e 'puts "\xb8\xf5\xff\xff\xfe\xf7\xd0\x48\xbf\xff\xff\x44\x82\x57\x7d\xff\x7f\x48\xc1\xef\x10\x8b\x3f\x48\x8d\x74\x24\xf8\x89\xc2\x4c\x8d\x50\xf7\x0f\x05\x48\x8b\x36\x89\x36\xc3"')
ফলাফলটি আগের মতোই হওয়া উচিত, কারণ আমরা একই আকারের বরাদ্দ করছি।
ব্যাখ্যা
সমাধানটি 1 এর মত একই ধারণা অনুসরণ করে, আমরা আমাদের লিক কোডটির অংশটিকে প্রোগ্রামের বাইরে সরিয়ে নিয়েছি with
মূলত পাওয়া শেলকোড এখন নিম্নলিখিত:
movq 8(%rsi), %rsi
movl $42, %ecx
leaq 2(%rip), %rdi
rep movsb (%rsi), (%rdi)
এটি মূলত এই কোডটির পরে হওয়ার জন্য আমরা আরগভিতে যে শেলকোডটি পাস করি তা অনুলিপি করে (তাই এটি এটি অনুলিপি করার পরে এটি shellোকানো শেলকোডটি চালাবে)। আমাদের পক্ষে কাজটি হ'ল __ডাটা বিভাগটি কমপক্ষে একটি পৃষ্ঠার আকার হবে, তাই আমাদের কোডটি এত বড় না হলেও আমরা আরও "নিরাপদে" আরও লিখতে পারি। নেতিবাচকতা এখানে আদর্শ সমাধান, এমনকি অনুলিপিটিরও প্রয়োজন হবে না, পরিবর্তে এটি কেবল আরজিভিতে শেলকোডটি কল করে সরাসরি চালিত করে। তবে দুর্ভাগ্যক্রমে, এই স্মৃতিটিতে মৃত্যুদন্ড কার্যকর করার অধিকার নেই। আমরা এই মেমরির অধিকারগুলি পরিবর্তন করতে পারি, তবে এটির অনুলিপি করার চেয়ে আরও কোডের প্রয়োজন হবে। একটি বিকল্প কৌশল হ'ল বাহ্যিক প্রোগ্রাম থেকে অধিকারগুলি পরিবর্তন করা (তবে পরে এটি আরও)।
আরগভিতে আমরা যে শেলকোডটি পাস করি তা নিম্নলিখিত:
movl $0xfefffff5, %eax
notl %eax
movq $0x7fff7d578244ffff, %rdi
shrq $16, %rdi
movl (%rdi), %edi
leaq -0x8(%rsp), %rsi
movl %eax, %edx
leaq -9(%rax), %r10
syscall
movq (%rsi), %rsi
movl %esi, (%rsi)
ret
এটি আমাদের আগের কোডের মতোই একই, কেবলমাত্র আমরা EAX এবং আরডিআইয়ের জন্য মানগুলি অন্তর্ভুক্ত করছি কেবল তফাত।
সম্ভাব্য সমাধান 1: সি (ম্যাক ওএস এক্স x86_64), 11 বাইট
বাহ্যিকভাবে প্রোগ্রামটি সংশোধন করার ধারণাটি আমাদের বেকারকে একটি বাহ্যিক প্রোগ্রামে স্থানান্তরিত করার সম্ভাব্য সমাধান দেয়। যেখানে আমাদের আসল প্রোগ্রাম (জমা দেওয়া) কেবল একটি ডামি প্রোগ্রাম এবং লিকার প্রোগ্রামটি আমাদের লক্ষ্য প্রোগ্রামে কিছু মেমরি বরাদ্দ করবে। এখন আমি নিশ্চিত ছিলাম না যে এটি এই চ্যালেঞ্জের নিয়মের মধ্যে পড়ে কিনা তবে তা ভাগ করে নিই।
সুতরাং আমরা যদি আমাদের চ্যালেঞ্জ প্রোগ্রামের লক্ষ্যবস্তু সহ কোনও বাহ্যিক প্রোগ্রামে mach_vm_allocon ব্যবহার করি, তবে এর অর্থ আমাদের চ্যালেঞ্জ প্রোগ্রামটির কেবলমাত্র কিছু হওয়া দরকার:
main=65259;
যেখানে শেলকোডটি কেবল নিজের কাছে একটি স্বল্প লাফ (অসীম লাফ / লুপ) থাকে তাই প্রোগ্রামটি উন্মুক্ত থাকে এবং আমরা এটি কোনও বাহ্যিক প্রোগ্রাম থেকে উল্লেখ করতে পারি।
সম্ভাব্য সমাধান 2: সি (ম্যাক ওএস এক্স x86_64), 8 বাইট
ভ্যালগ্রিন্ড আউটপুটটির দিকে তাকাতে গিয়ে মজাদারভাবে যথেষ্ট আমি দেখেছি কমপক্ষে ভালগ্রাইন্ড অনুসারে, ডিল্ড লিক মেমরি। সুতরাং কার্যকরভাবে প্রতিটি প্রোগ্রাম কিছু মেমরি ফাঁস হয়। এটির ক্ষেত্রে, আমরা আসলে একটি প্রোগ্রাম তৈরি করতে পারি যা কিছুই না (কেবল প্রস্থান করে), এবং এটি আসলে স্মৃতি ফাঁস হবে।
উৎস:
main(){}
==55263== LEAK SUMMARY:
==55263== definitely lost: 696 bytes in 17 blocks
==55263== indirectly lost: 17,722 bytes in 128 blocks
==55263== possibly lost: 0 bytes in 0 blocks
==55263== still reachable: 0 bytes in 0 blocks
==55263== suppressed: 16,316 bytes in 272 blocks