Reverse Python Bytecode

Trong quá trình làm CTF ở giải AmateursCTF2023, tôi có gặp 1 bài trong mảng Reverse sử dụng file .pyc được biên dịch bởi python 3.10. Các bạn có thể tải challenge ở đây trick-question.pyc.
Solutions
Đầu tiên khi gặp 1 file .pyc ta sẽ sử dụng pydumpck để dump được ra file .py các bạn có thể xem thêm về pydumpck ở đây pydumpck.
Sau khi dump file ta có 1 folder output trong này sẽ xuất hiện file .py cần thiết của chúng ta.

Đây là code của chương trình sau khi dump thành công sau khi nhìn qua 1 lượt thì thấy có khả năng nó sẽ đảo ngược chuỗi rồi decode lại với base64 cho mình vì vậy tôi tiến hành fix và chạy code này.
b64decode = lambda x: id.__self__.__dict__['exec'](id.__self__.__dict__['__import__']('base64').b64decode(x))
r = [0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0]
x = ['gIHByaW50KCJJbmNvcnJlY3QuIik=', 'gcHJpbnQoIkNvcnJlY3QhIikKZWxzZToKIC', 'CIgogOpkiIgozZhxmZgUGa0BiclRnbFJCK0VHculGKrNWZoNGImlmCp0HZpBiOnQWansHIsUGZvNGKps2Ylh2YoUGc5RHI9', 'yajVGajpgCpkCKgwSKo', 'xXHgwY1x4MDInLC', 'DecNGM4xlMwgHX2EDecFDM4x1YwgHXx', 'xXHgwNFx4MDJceDBjXHgwMVx4MDhceD', 'DecNGM4xlMwgHX2EDM4x1YwgHXy', 'xMlx4MDJceDBjXHgwMTJceD', 'DecNGM4xlMwgHXwEDecFDM4x1YwgHXy', 'DecBTM4xVMwgHXlBDecFDM4xFOxgHXx', 'DecVGM4xlMwgHXwEDecFDM4x1YwgHXy', 'DecJSMwgHXjBDecNDM4xlbx', 'xXHgwZVx4MDJceDE2XHgwMVx4MGNceD', 'xXHgwMlx4ODBceDBjXHgwMVx4MGNceD', 'Dec5GXx', 'DechDM4xVMwgHX4EDecJDM4xFNwgHXx', 'xXHgwY1x4MDFceDE0XHgwMlx4MGNceD', 'xXHgwY1x4MDFceDBjXHgwMVx4MGNceD', 'DecBTM4x1JiBCLz', 'nY2hlY2snLC', 'ncicsICdjJyksICcnLC', 'nc2h1ZmZsZScsICdmcm9tX2J5dGVzJywgJ3JhbmRpbnQnKSwgKCdpbnB1dCcsICd1bmRlcnNjb3JlcycsICdpJywgJ3gnLC', 'CLnQWZlN3JgwyJ0NXZnlGZ4VGan', 'nYXBwZW5kJywgJ2VuY29kZScsICdzcGxpdCcsICdzaGEyNTYnLC', 'CLn81X0NWak91Xn', 'nX19zZWxmX18nLC', 'nVHJ1ZScsICdEaWQgeW91IGtub3c/IHB5Y2RjIGNhbiBkZWNvbXBpbGUgbWFyc2hhbGVkIGNvZGUgb2JqZWN0cy4gSnVzdCBtYWtlIHN1cmUgeW91IG1lbnRpb24gdGhlIHJpZ2h0IHZlcnNpb24hJyksICgnaWQnLC', 'CLnMjZyYWY5YTZlljM4BzJgwyJ4VGan', 'CL4ITMgwiNgwiN4gjN4', 'zN3IDNgwyJw', 'DecdiYgwiMyETO5ETNygDIsgDIsEjN1', 'TM4cjMyQDIsUTOycjN5QTOyQDIscSZsRHdpx2JgwSNgwyJ05Wan', 'xMDgsIDUyKSwgNCwgYidmcmVlYmllJywgYicwZmZyZWViaWUnLC', 'CL5', 'TMgwiMwEDIskDOgwSO0gCIsMDIscCdzlGbn', 'CLn02bk5WYydCIscSY4YmYhR2YhNmZxMTN1IGOwI2Y4IzMkZ2MkFjMxQGNiJDMkFDN2gDNmRDO4YmNjFjNjZWMkRGNkdzN3cjMyIGNn', 'CLnIWash2chh2JgwyJf9Fdy9Gctl2XfdCIskCNz', 'sIDY4LC', 'jNxgCIsIDIsEDIscCUZdDaw42cnIGIs', 'DIscyXnIGIskSNz', 'sIDIzLC', 'xMywgMj', 'CLxEDIscDKgwyJfdCIscSZ0Fmcl1WduV2JgwiM0', 'CLn4WZsdCIscSfn', 'CLx0CIscSZzxWYGdCIscyeGR1QzJXdlRXYtF2JgwiMx', 'CLl52bOhCIscCMwgHXTBDM4xVOxgHXoQmMwgHXqFDM4xlaw', 'DecRHMwgHXTBDM4xVOxgHXz', 'walx4MDFqXHgwMmRceD', 'zXHg5MFx4MDFyXHg4MHRceD', 'Dect2JcRWMwgHXzgDecVDM4xFfw', 'xalx4MDJkJlx4MTlceD', 'DecpGMwgHX0NWcx', 'yN1x4MDB9XHgwNVx4OTBceD', 'DecxXNwgHX8VDM4xVfw', 'yfFx4MDVkJTlceD', 'Dec1nYwgHXdBDM4xFRw', '1fFx4MDBkJFx4MTlceD', 'Dec13YwgHXkBDM4x1Uw', 'DeclTM4x1MwgHXkJDM4xlax', 'xcl10XHgwMGpceD', 'wZCNrXHgwM1x4OTBceD', 'yfFx4MDRceGEwXHgwYmRceDBjZFx4MWVceGExXHgwMkFceD', 'DecFTY4xFZxgHXkBDM4x1NxgHXiQGMwgHX5EDecJDM4xVN4gHXx', 'walx4MDFqXHgwMmRceDFiXHgxOVx4MDBceGEwXG58XHgwMGRceDFjXHgxOVx4MDBkIGRceD', 'DecRHMwgHXTBDM4xVOxgHXz', 'walx4MDFqXHgwMmRceD', 'DecRHPyFDM4xFM5gHXz', 'DectWIkBDM4xVQy', 'walx4MDFqXHgwMmRceDFiXHgxOVx4MDBceGEwXG58XHgwMGRceDFjXHgxOVx4MDBkXHgxOGQgXHg4NVx4MDJceDE5XHgwMGRceDFkXHhhMVx4MDJ8XHgwNFx4YTBceDBiZFx4MGNkXHgxZVx4YTFceD', 'DecRHMwgHXTBDM4xVOxgHXz', 'walx4MDFqXHgwMmRceD', 'DecRHZxgHXyFDM4xFM5gHXz', 'DectmZxgHXkBDM4xVQy', 'walx4MDFqXHgwMmRceDFiXHgxOVx4MDBceGEwXG58XHgwMGRceDFjXHgxOVx4MDBkXHgwY2RceDE4XHg4NVx4MDJceDE5XHgwMGRceDFkXHhhMVx4MDJ8XHgwNFx4YTBceDBiZFx4MGNkXHgxZVx4YTFceD', 'DecRHMwgHXTBDM4xVOxgHXz', 'DecRmMwgHXqFDM4xlaw', 'DecRXZmhHXyNDM4x1ahFDecRGMwgHX3EDeclTM4xFZw', 'DeclTM4xFOxgHXkBDM4xFfw', 'DecNFMwgHX5EDecNDM4xFZy', 'DecpWMwgHXqBDM4xFdwYGecJ3MwgHXrFDM4xlMhhHX3EDecRGMwgHXnBDM4xVOxgHX2EDecRGMwgHX8BDM4xVMwgHXx', 'wZFx4MTZceDE5XHgwMFx4YTFceD', 'wXHg4M1x4MDF8XHgwMGRceDE2PFx4MDB8XHgwNFx4YTBcdHxceD', 'wfFx4MDBkXHgxNlx4MTlceD', 'DeclTM4xlcz', 'Dect2MxgHXkBDM4xVMhhHX3', 'xXHhhMFx4MDZ8XHgwMGRceDBmXHgxOVx4MDBceGExXHgwMVx4YTBceD', 'DecNDO4xlMxgHXkBDM4xVOxgHXxEDecRmMwgHXqFDM4xlaw', 'zXHgxOVx4MDBTXHgwMHRceD', 'walx4MDFqXHgwMmRceD', 'DecRXOhhHXyNDM4x1awEDecR2MwgHXmBDM4xFOxgHXw', 'wXHgxN1x4MDB8XHgwMGRceDBlXHgxOVx4MDBkXHgwZVx4MTlceD', 'wZFx4MGVceDE5XHgwMGRceDBmXHgxOVx4MDB8XHgwMGRceDBlXHgxOVx4MDBkXHgwY1x4MTlceD', 'DecxHMwgHX4EDecBDM4xVOxgHXjBDecRGMwgHX5EDecVGM4xFZw', 'DecxHMwgHX3EDecBDM4xVOxgHXmBDecRGMwgHX5EDecVGM4xFZw', 'wZFx4MGVceDE5XHgwMHxceD', 'wfFx4MDBkXHgwZVx4MTlceD', 'wZFx4MGZceDE5XHgwMFx4MThceD', 'wfFx4MDBkXHgwZVx4MTlceD', 'wZFx4MGVceDE5XHgwMFx4MTdceD', 'DeclTM4xVZwgHXkBDM4xFfw', 'DeclTM4x1YwgHXkBDM4xVOxgHXlBDecRGMwgHX8BDM4x1Uw', 'xalx4MDJkXHgwM1x4MTlceD', 'zcmx0XHgwMGpceD', '0XHg4NVx4MDNceDE5XHgwMGRccmtceD', 'wZFx4MDBkXHgwMGRceD', 'wfFx4MDBkXHgwY1x4MTlceD', 'Dec1XMwgHXxEGecJGM4xFZ1', 'DecBTY4xFMwgHXxEGecRDM4xFMhhHXw', 'zXHgxOVx4MDBTXHgwMHxceD', 'DecRmMwgHXqFDM4xlaw', 'xa1x4MDNyVHRceD', 'xXHgwMHE6fFx4MDFnXHgwMGRcblx4YTJceD', 'yXHhhMVx4MDFceD', 'Decx3MwgHXwEGecFDM4xFfHJnMwgHXrRHXkNDM4xFfz', 'xRFx4MDBdXHJcXFx4MDJ9XHgwMn1ceD', '4XHgxOVx4MDB8XHgwMFx4ODNceD', 'DecRmMwgHXqFDM4xlaw', 'DecRXMwgHX9BDM4x1Zw', 'DecNFMwgHX5EDecNDM4xFZy', 'DecpWMwgHXqBDM4xFdwI3MwgHXrdDM4xFZx', '2XHgxOVx4MDB8XHgwMFx4ODNceD', 'DecRmMwgHXqFDM4xlaw', 'DecRHMwgHX9BDM4xVOxgHXy', 'wZFx4MDFkXHgwNFx4ODVceD', 'DecxHMwgHXTBDM4xVOxgHXz', 'DecRmMwgHXqFDM4xlaw', 'DecRXYxgHXyNDM4x1a1', 'wZFx4MDRceDE5XHgwMGRceD', 'zXHgxOVx4MDBTXHgwMHxceD', 'DecRmMwgHXqFDM4xlaw', 'ya1x4MDNyXHgwZXRceD', 'xXHg4NVx4MDJceDE5XHgwMGRceD', 'Y2hlY2sgPSBsYW1iZGE6Tm9uZQpjb2RlID0gdHlwZShjaGVjay5fX2NvZGVfXykoMSwgMCwgMCwgNiwgNSwgNjcsIGInfFx4MDBkXHgwMGRceD']
for i in range(len(r)):
if r[i]:
x[i] = x[i][::-1]
b64decode('A'.join(x[::-1]))
- Tại đây ta sẽ sửa file và ghi output khi chạy file python này ra 1 file mới .
import base64
def b64decode(x):
return base64.b64decode(x)
r = [0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0]
x = ['gIHByaW50KCJJbmNvcnJlY3QuIik=', 'gcHJpbnQoIkNvcnJlY3QhIikKZWxzZToKIC', 'CIgogOpkiIgozZhxmZgUGa0BiclRnbFJCK0VHculGKrNWZoNGImlmCp0HZpBiOnQWansHIsUGZvNGKps2Ylh2YoUGc5RHI9', 'yajVGajpgCpkCKgwSKo', 'xXHgwY1x4MDInLC', 'DecNGM4xlMwgHX2EDecFDM4x1YwgHXx', 'xXHgwNFx4MDJceDBjXHgwMVx4MDhceD', 'DecNGM4xlMwgHX2EDM4x1YwgHXy', 'xMlx4MDJceDBjXHgwMTJceD', 'DecNGM4xlMwgHXwEDecFDM4x1YwgHXy', 'DecBTM4xVMwgHXlBDecFDM4xFOxgHXx', 'DecVGM4xlMwgHXwEDecFDM4x1YwgHXy', 'DecJSMwgHXjBDecNDM4xlbx', 'xXHgwZVx4MDJceDE2XHgwMVx4MGNceD', 'xXHgwMlx4ODBceDBjXHgwMVx4MGNceD', 'Dec5GXx', 'DechDM4xVMwgHX4EDecJDM4xFNwgHXx', 'xXHgwY1x4MDFceDE0XHgwMlx4MGNceD', 'xXHgwY1x4MDFceDBjXHgwMVx4MGNceD', 'DecBTM4x1JiBCLz', 'nY2hlY2snLC', 'ncicsICdjJyksICcnLC', 'nc2h1ZmZsZScsICdmcm9tX2J5dGVzJywgJ3JhbmRpbnQnKSwgKCdpbnB1dCcsICd1bmRlcnNjb3JlcycsICdpJywgJ3gnLC', 'CLnQWZlN3JgwyJ0NXZnlGZ4VGan', 'nYXBwZW5kJywgJ2VuY29kZScsICdzcGxpdCcsICdzaGEyNTYnLC', 'CLn81X0NWak91Xn', 'nX19zZWxmX18nLC', 'nVHJ1ZScsICdEaWQgeW91IGtub3c/IHB5Y2RjIGNhbiBkZWNvbXBpbGUgbWFyc2hhbGVkIGNvZGUgb2JqZWN0cy4gSnVzdCBtYWtlIHN1cmUgeW91IG1lbnRpb24gdGhlIHJpZ2h0IHZlcnNpb24hJyksICgnaWQnLC', 'CLnMjZyYWY5YTZlljM4BzJgwyJ4VGan', 'CL4ITMgwiNgwiN4gjN4', 'zN3IDNgwyJw', 'DecdiYgwiMyETO5ETNygDIsgDIsEjN1', 'TM4cjMyQDIsUTOycjN5QTOyQDIscSZsRHdpx2JgwSNgwyJ05Wan', 'xMDgsIDUyKSwgNCwgYidmcmVlYmllJywgYicwZmZyZWViaWUnLC', 'CL5', 'TMgwiMwEDIskDOgwSO0gCIsMDIscCdzlGbn', 'CLn02bk5WYydCIscSY4YmYhR2YhNmZxMTN1IGOwI2Y4IzMkZ2MkFjMxQGNiJDMkFDN2gDNmRDO4YmNjFjNjZWMkRGNkdzN3cjMyIGNn', 'CLnIWash2chh2JgwyJf9Fdy9Gctl2XfdCIskCNz', 'sIDY4LC', 'jNxgCIsIDIsEDIscCUZdDaw42cnIGIs', 'DIscyXnIGIskSNz', 'sIDIzLC', 'xMywgMj', 'CLxEDIscDKgwyJfdCIscSZ0Fmcl1WduV2JgwiM0', 'CLn4WZsdCIscSfn', 'CLx0CIscSZzxWYGdCIscyeGR1QzJXdlRXYtF2JgwiMx', 'CLl52bOhCIscCMwgHXTBDM4xVOxgHXoQmMwgHXqFDM4xlaw', 'DecRHMwgHXTBDM4xVOxgHXz', 'walx4MDFqXHgwMmRceD', 'zXHg5MFx4MDFyXHg4MHRceD', 'Dect2JcRWMwgHXzgDecVDM4xFfw', 'xalx4MDJkJlx4MTlceD', 'DecpGMwgHX0NWcx', 'yN1x4MDB9XHgwNVx4OTBceD', 'DecxXNwgHX8VDM4xVfw', 'yfFx4MDVkJTlceD', 'Dec1nYwgHXdBDM4xFRw', '1fFx4MDBkJFx4MTlceD', 'Dec13YwgHXkBDM4x1Uw', 'DeclTM4x1MwgHXkJDM4xlax', 'xcl10XHgwMGpceD', 'wZCNrXHgwM1x4OTBceD', 'yfFx4MDRceGEwXHgwYmRceDBjZFx4MWVceGExXHgwMkFceD', 'DecFTY4xFZxgHXkBDM4x1NxgHXiQGMwgHX5EDecJDM4xVN4gHXx', 'walx4MDFqXHgwMmRceDFiXHgxOVx4MDBceGEwXG58XHgwMGRceDFjXHgxOVx4MDBkIGRceD', 'DecRHMwgHXTBDM4xVOxgHXz', 'walx4MDFqXHgwMmRceD', 'DecRHPyFDM4xFM5gHXz', 'DectWIkBDM4xVQy', 'walx4MDFqXHgwMmRceDFiXHgxOVx4MDBceGEwXG58XHgwMGRceDFjXHgxOVx4MDBkXHgxOGQgXHg4NVx4MDJceDE5XHgwMGRceDFkXHhhMVx4MDJ8XHgwNFx4YTBceDBiZFx4MGNkXHgxZVx4YTFceD', 'DecRHMwgHXTBDM4xVOxgHXz', 'walx4MDFqXHgwMmRceD', 'DecRHZxgHXyFDM4xFM5gHXz', 'DectmZxgHXkBDM4xVQy', 'walx4MDFqXHgwMmRceDFiXHgxOVx4MDBceGEwXG58XHgwMGRceDFjXHgxOVx4MDBkXHgwY2RceDE4XHg4NVx4MDJceDE5XHgwMGRceDFkXHhhMVx4MDJ8XHgwNFx4YTBceDBiZFx4MGNkXHgxZVx4YTFceD', 'DecRHMwgHXTBDM4xVOxgHXz', 'DecRmMwgHXqFDM4xlaw', 'DecRXZmhHXyNDM4x1ahFDecRGMwgHX3EDeclTM4xFZw', 'DeclTM4xFOxgHXkBDM4xFfw', 'DecNFMwgHX5EDecNDM4xFZy', 'DecpWMwgHXqBDM4xFdwYGecJ3MwgHXrFDM4xlMhhHX3EDecRGMwgHXnBDM4xVOxgHX2EDecRGMwgHX8BDM4xVMwgHXx', 'wZFx4MTZceDE5XHgwMFx4YTFceD', 'wXHg4M1x4MDF8XHgwMGRceDE2PFx4MDB8XHgwNFx4YTBcdHxceD', 'wfFx4MDBkXHgxNlx4MTlceD', 'DeclTM4xVNxgHXkJDM4xlax', 'DecpGMwgHX0BDM4xVMwgHXx', 'DecFTY4xFMwgHX5EDecZGM4xFZw', 'DecxHOwgHXwEGecRDM4xFf0', 'wZFx4MTRceDgzXHgwMX1ceD', 'DeclTM4xVMxgHXkJDM4xlax', 'DecpGMwgHX0BDM4x1Uw', 'DeclTM4x1MwgHXkJDM4xlax', 'DecpGMwgHX0BzY4xlcz', 'Dect2MxgHXkBDM4xVMhhHX3', 'xXHhhMFx4MDZ8XHgwMGRceDBmXHgxOVx4MDBceGExXHgwMVx4YTBceD', 'DecNDO4xlMxgHXkBDM4xVOxgHXxEDecRmMwgHXqFDM4xlaw', 'zXHgxOVx4MDBTXHgwMHRceD', 'walx4MDFqXHgwMmRceD', 'DecRXOhhHXyNDM4x1awEDecR2MwgHXmBDM4xFOxgHXw', 'wXHgxN1x4MDB8XHgwMGRceDBlXHgxOVx4MDBkXHgwZVx4MTlceD', 'wZFx4MGVceDE5XHgwMGRceDBmXHgxOVx4MDB8XHgwMGRceDBlXHgxOVx4MDBkXHgwY1x4MTlceD', 'DecxHMwgHX4EDecBDM4xVOxgHXjBDecRGMwgHX5EDecVGM4xFZw', 'DecxHMwgHX3EDecBDM4xVOxgHXmBDecRGMwgHX5EDecVGM4xFZw', 'wZFx4MGVceDE5XHgwMHxceD', 'wfFx4MDBkXHgwZVx4MTlceD', 'wZFx4MGZceDE5XHgwMFx4MThceD', 'wfFx4MDBkXHgwZVx4MTlceD', 'wZFx4MGVceDE5XHgwMFx4MTdceD', 'DeclTM4xVZwgHXkBDM4xFfw', 'DeclTM4x1YwgHXkBDM4xVOxgHXlBDecRGMwgHX8BDM4x1Uw', 'xalx4MDJkXHgwM1x4MTlceD', 'zcmx0XHgwMGpceD', '0XHg4NVx4MDNceDE5XHgwMGRccmtceD', 'wZFx4MDBkXHgwMGRceD', 'wfFx4MDBkXHgwY1x4MTlceD', 'Dec1XMwgHXxEGecJGM4xFZ1', 'DecBTY4xFMwgHXxEGecRDM4xFMhhHXw', 'zXHgxOVx4MDBTXHgwMHxceD', 'DecRmMwgHXqFDM4xlaw', 'xa1x4MDNyVHRceD', 'xXHgwMHE6fFx4MDFnXHgwMGRcblx4YTJceD', 'yXHhhMVx4MDFceD', 'Decx3MwgHXwEGecFDM4xFfHJnMwgHXrRHXkNDM4xFfz', 'xRFx4MDBdXHJcXFx4MDJ9XHgwMn1ceD', '4XHgxOVx4MDB8XHgwMFx4ODNceD', 'DecRmMwgHXqFDM4xlaw', 'DecRXMwgHX9BDM4x1Zw', 'DecNFMwgHX5EDecNDM4xFZy', 'DecpWMwgHXqBDM4xFdwI3MwgHXrdDM4xFZx', '2XHgxOVx4MDB8XHgwMFx4ODNceD', 'DecRmMwgHXqFDM4xlaw', 'DecRHMwgHX9BDM4xVOxgHXy', 'wZFx4MDFkXHgwNFx4ODVceD', 'DecxHMwgHXTBDM4xVOxgHXz', 'DecRmMwgHXqFDM4xlaw', 'DecRXYxgHXyNDM4x1a1', 'wZFx4MDRceDE5XHgwMGRceD', 'zXHgxOVx4MDBTXHgwMHxceD', 'DecRmMwgHXqFDM4xlaw', 'ya1x4MDNyXHgwZXRceD', 'xXHg4NVx4MDJceDE5XHgwMGRceD', 'Y2hlY2sgPSBsYW1iZGE6Tm9uZQpjb2RlID0gdHlwZShjaGVjay5fX2NvZGVfXykoMSwgMCwgMCwgNiwgNSwgNjcsIGInfFx4MDBkXHgwMGRceD']
for i in range(len(r)):
if r[i]:
x[i] = x[i][::-1]
result = b64decode('A'.join(x[::-1]))
print(result)
with open('solve.py', 'w') as file:
file.write(result.decode('utf-8'))
- Đây chính là đoạn code sau khi ta chạy file nó đã gen ra những bytecode trong python và có 1 chuỗi làm tôi chú ý đến 'Did you know? pycdc can decompile marshaled code objects. Just make sure you mention the right version!'. Có thể tác giả của bài này đang hướng tôi đến việc sử dụng pycdc để decompile lại file ban đầu bằng những bytecode. Nhưng lúc này tôi vẫn chưa biết bytecode là gì 😞.
check = lambda:None
code = type(check.__code__)(1, 0, 0, 6, 5, 67, b'|\x00d\x00d\x01\x85\x02\x19\x00d\x02k\x03r\x0et\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x04\x19\x00d\x05k\x03r\x1at\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x01d\x04\x85\x02\x19\x00}\x00t\x00j\x01j\x02d\x06\x19\x00|\x00\x83\x01d\x07k\x03r0t\x00j\x01j\x02d\x03\x19\x00S\x00g\x00}\x01t\x00j\x01j\x02d\x08\x19\x00|\x00\x83\x01D\x00]\r\\\x02}\x02}\x03|\x03d\tk\x02rG|\x01\xa0\x03|\x02\xa1\x01\x01\x00q:|\x01g\x00d\n\xa2\x01k\x03rTt\x00j\x01j\x02d\x03\x19\x00S\x00|\x00\xa0\x04\xa1\x00\xa0\x05d\x0b\xa1\x01}\x00|\x00d\x0c\x19\x00d\x00d\x00d\x04\x85\x03\x19\x00d\rk\x03rlt\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x0e\x19\x00d\x0c\x19\x00|\x00d\x0e\x19\x00d\x0e\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0f\x19\x00\x18\x00|\x00d\x0e\x19\x00d\x0e\x19\x00|\x00d\x0e\x19\x00d\x0f\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0c\x19\x00\x18\x00|\x00d\x0e\x19\x00d\x0f\x19\x00|\x00d\x0e\x19\x00d\x0c\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0e\x19\x00\x18\x00f\x03d\x10k\x03r\xa9t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x11\x19\x00d\x12\x83\x01\xa0\x06|\x00d\x0f\x19\x00\xa1\x01\xa0\x07\xa1\x00d\x13k\x03r\xc0t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x11\x19\x00d\x14\x83\x01}\x04|\x04\xa0\x08|\x00d\x0f\x19\x00\xa1\x01\x01\x00t\x00j\x01j\x02d\x15\x19\x00|\x00d\x16\x19\x00\x83\x01|\x00d\x16<\x00|\x04\xa0\t|\x00d\x16\x19\x00\xa1\x01\x01\x00|\x00d\x16\x19\x00g\x00d\x17\xa2\x01k\x03r\xf0t\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x18\x19\x00d\x19\x17\x00d\x1ak\x03r\xfet\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d\x0cd\x18\x85\x02\x19\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d\x1fk\x03\x90\x01r\x1dt\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d\x18d \x85\x02\x19\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d!k\x03\x90\x01r<t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d d\x01\x85\x02\x19\x00d"\x17\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d#k\x03\x90\x01r]t\x00j\x01j\x02d\x03\x19\x00S\x00d\x0c}\x05|\x00d$\x19\x00D\x00]\x0b}\x02|\x05d%9\x00}\x05|\x05|\x027\x00}\x05\x90\x01qct\x00j\x01j\x02d&\x19\x00|\x05\x83\x01d\'k\x03\x90\x01r\x80t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d(\x19\x00S\x00', (None, 12, 'amateursCTF{', 'False', -1, '}', 'len', 42, 'enumerate', '_', (7, 11, 13, 20, 23, 35), b'_', 0, b'sn0h7YP', 1, 2, (160, 68, 34), '__import__', 'hashlib', '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a', 'random', 'list', 3, (49, 89, 102, 109, 108, 52), 4, b'freebie', b'0ffreebie', 'int', 5, 'little', 4294967295, 4227810561, 8, 825199122, b'\x00', 4277086886, 6, 128, 'hex', '0x29ee69af2f3', 'True', 'Did you know? pycdc can decompile marshaled code objects. Just make sure you mention the right version!'), ('id', '__self__', '__dict__', 'append', 'encode', 'split', 'sha256', 'hexdigest', 'seed', 'shuffle', 'from_bytes', 'randint'), ('input', 'underscores', 'i', 'x', 'r', 'c'), '', 'check', 3, b'\x10\x01\x0c\x01\x0c\x01\x0c\x01\x0c\x01\x14\x02\x0c\x01\x04\x02\x18\x01\x08\x01\n\x01\x02\x80\x0c\x01\x0c\x01\x0e\x02\x16\x01\x0c\x01n\x03\x0c\x01"\x02\x0c\x01\x10\x02\x0e\x01\x18\x01\x0e\x01\x10\x02\x0c\x01\x10\x02\x0c\x012\x02\x0c\x012\x02\x0c\x016\x02\x0c\x01\x04\x02\x0c\x01\x08\x01\x0c\x01\x16\x02\x0c\x01\x0c\x02', (), ())
check = type(check)(code, {'id': id})
if check(input("Enter the flag: ")):
print("Correct!")
else:
print("Incorrect.")
- Tôi đã tìm hiểu 1 lúc và tóm tắt lại được 1 số chú ý. Bytecode trong Python là một dạng mã trung gian (intermediate code) được sử dụng bởi trình thông dịch Python để thực thi các chương trình Python. Khi bạn viết mã Python, trình thông dịch sẽ chuyển đổi mã nguồn Python của bạn thành bytecode trước khi thực thi mã. Bytecode là một dạng mã hợp ngữ giống như mã máy, nhưng thay vì chạy trực tiếp trên máy tính, nó sẽ chạy trong môi trường của trình thông dịch Python.
Dưới đây là một số thông tin cơ bản về bytecode Python:
Định dạng bytecode: Bytecode Python là một chuỗi các mã byte (bytecode) duy nhất. Mỗi bytecode thể hiện một hoạt động cụ thể mà trình thông dịch Python thực hiện. Ví dụ, có bytecode cho việc gán giá trị, tính toán, thực thi các hàm, kiểm tra điều kiện, v.v.
Độc lập nền tảng: Bytecode Python là độc lập nền tảng, điều đó có nghĩa là bạn có thể viết mã Python trên một nền tảng như Windows và chạy nó trên một nền tảng khác như Linux hoặc macOS mà không cần viết lại mã nguồn. Điều này được thực hiện bởi trình thông dịch Python, giúp code Python trở nên di động và dễ dàng chạy trên nhiều hệ điều hành.
Tốc độ thực thi: Bytecode Python được thiết kế để giảm độ phức tạp của việc thực thi mã nguồn Python so với việc thực thi mã nguồn gốc. Mã bytecode thường nhanh hơn khi thực thi, do đó giúp cải thiện hiệu suất trong quá trình chạy mã Python.
PVM - Python Virtual Machine: Python Virtual Machine (PVM) là một phần mềm giả lập máy ảo mà thực thi bytecode Python. Khi bạn chạy một chương trình Python, trình thông dịch sẽ sử dụng PVM để thực thi bytecode.
.pyc và .pyo files: Khi bạn chạy một chương trình Python, trình thông dịch sẽ biên dịch mã nguồn thành bytecode và lưu trữ nó trong các tệp có đuôi .pyc (Python Compiled) hoặc .pyo (Python Optimized). Các tệp này sẽ được sử dụng lần sau bạn chạy chương trình, giúp giảm thời gian biên dịch lại mã nguồn.
Disassembly: Bạn có thể xem mã bytecode của một module Python bằng cách sử dụng module
dis. Module này cung cấp các công cụ giúp bạn hiểu cách bytecode hoạt động.Đọc và ghi bytecode: Nếu bạn muốn tùy chỉnh hoặc xử lý bytecode trực tiếp, Python cung cấp các module như
marshalđể đọc và ghi bytecode từ và vào các tệp.
Cùng theo hướng của tác giả sau khi tìm 1 số tools decompile bytecode python thì tôi thấy tại đây Pycdc được recommend nhiều nhất.

Theo hướng dẫn thì ta sẽ sử dụng marshal.dumps để biên dịch ra file .pyc sau đó sẽ dump lại ra file .py với version 3.10 của python. Tiến hành sửa code từ chương trình cũ.

Đến đây ta đã có file dumps.pyc => thực hiện dump ra file .py với version 10. Theo hướng dẫn ở trên ta sẽ sử dụng pycdc để decompile.

Đây chính là phần code đầy đủ của chương trình. Nếu bạn vẫn cảm thấy quá khó đọc thì ta sẽ sử dụng chatGPT để sửa lại code cho dễ đọc hơn. Đây là phiên bản code sau khi đã qua tay của chatGPT và đừng quên phần input đã comment ở bên trên.
def validate_flag(input_flag):
if input_flag[:12] != 'amateursCTF{':
return False
if input_flag[-1] != '}':
return False
input_flag = input_flag[12:-1]
if len(input_flag) != 42:
return False
underscores = []
for i, x in enumerate(input_flag):
if x == '_':
underscores.append(i)
if underscores != [7, 11, 13, 20, 23, 35]:
return False
input_parts = input_flag.encode().split(b'_')
if input_parts[0][::-1] != b'sn0h7YP':
return False
if (input_parts[1][0] + input_parts[1][1] - input_parts[1][2], input_parts[1][1] + input_parts[1][2] - input_parts[1][0], input_parts[1][2] + input_parts[1][0] - input_parts[1][1]) != (160, 68, 34):
return False
import hashlib
if hashlib.sha256(input_parts[2]).hexdigest() != '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a':
return False
import random
random.seed(input_parts[2])
input_parts[3] = list(input_parts[3])
random.shuffle(input_parts[3])
if input_parts[3] != [49, 89, 102, 109, 108, 52]:
return False
if input_parts[4] + b'freebie' != b'0ffreebie':
return False
xor_results = [
int.from_bytes(input_parts[5][0:4], 'little') ^ random.randint(0, 0xFFFFFFFF),
int.from_bytes(input_parts[5][4:8], 'little') ^ random.randint(0, 0xFFFFFFFF),
int.from_bytes(input_parts[5][8:12], 'little') ^ random.randint(0, 0xFFFFFFFF)
]
if xor_results != [0xFBFF4501, 825199122, 0xFEEF2AA6]:
return False
c = 0
for i in input_parts[6]:
c *= 128
c += i
if hex(c) != '0x29ee69af2f3':
return False
return True
user_input = input("Flag: ")
if validate_flag(user_input):
print("Correct")
else:
print("Incorrect")
Đến đây cũng cảm thấy khá nhẹ nhàng rồi ta sẽ reverse từng đoạn code 1. Đầu tiên input sẽ check xem 12 kí tự đầu tiên có phải là
amateursCTF{và kí tự cuối có phải là `}` hay không.if input_flag[:12] != 'amateursCTF{': return False if input_flag[-1] != '}': return FalseTiếp theo input sẽ cắt chuỗi bỏ phần đầu đi 12 kí tự và số lượng kí tự của flag còn lại là 42 kí tự. Sau đó nó sẽ append những vị trí có dấu `_` cho flag.
input_flag = input_flag[12:-1] if len(input_flag) != 42: return False underscores = [] for i, x in enumerate(input_flag): if x == '_': underscores.append(i) if underscores != [7, 11, 13, 20, 23, 35]: return Falseinput_parts = input_flag.encode().split(b'_') if input_parts[0][::-1] != b'sn0h7YP': return False if (input_parts[1][0] + input_parts[1][1] - input_parts[1][2], input_parts[1][1] + input_parts[1][2] - input_parts[1][0], input_parts[1][2] + input_parts[1][0] - input_parts[1][1]) != (160, 68, 34): return FalseLúc này flag sẽ được cắt làm 7 phần vì có 6 dấu _ xét phần thứ nhất nó bị đảo ngược chuỗi vậy nên lúc này
part[0]của nó sẽ mang giá trị làPY7h0ns.FLag lúc này
amateursCTF{PY7h0ns_xxx_x_xxxxxx_xx_xxxxxxxxxxx_xxxxxx}.Tiếp theo ta sẽ xử lý
part[1]vớiz3solver.from z3 import * a = Int('a') b = Int('b') c = Int('c') val = [ a + b - c == 160, b + c - a == 68, c + a - b == 34 ] s = Solver() s.add(val) if s.check() == sat: key = s.model() ar = key[a].as_long() br = key[b].as_long() cr = key[c].as_long() print(chr(ar) + chr(br) + chr(cr)) else: print("ko co")Sau khi chạy code ta được chuỗi
ar3.FLag lúc này
amateursCTF{PY7h0ns_ar3_x_xxxxxx_xx_xxxxxxxxxxx_xxxxxx}import hashlib if hashlib.sha256(input_parts[2]).hexdigest() != '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a': return False import random random.seed(input_parts[2]) input_parts[3] = list(input_parts[3]) random.shuffle(input_parts[3]) if input_parts[3] != [49, 89, 102, 109, 108, 52]: return False if input_parts[4] + b'freebie' != b'0ffreebie': return False xor_results = [ int.from_bytes(input_parts[5][0:4], 'little') ^ random.randint(0, 0xFFFFFFFF), int.from_bytes(input_parts[5][4:8], 'little') ^ random.randint(0, 0xFFFFFFFF), int.from_bytes(input_parts[5][8:12], 'little') ^ random.randint(0, 0xFFFFFFFF) ] if xor_results != [0xFBFF4501, 825199122, 0xFEEF2AA6]: return FalseTiếp tục phân tích đến
part[2]ta sẽ dử dụng brute force để tìm ra giá trị củapart[2].import hashlib import random def check(flag): print("check") hash_value = hashlib.sha256(flag.encode()).hexdigest() if hash_value != '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a': return False print("done") return True for i in range (256): if check(str(i)): print(i) breakVậy giá trị tìm được của
part[2] = 4.Tiếp tục phân tích code thì nhận ra 1 điểm tại đâyrandom.seed(input_parts[2])sẽ tạo ra việc khi ta gọirandom.seed()với cùng một giá trị đầu vào, bộ sinh số ngẫu nhiên sẽ được thiết lập ở trạng thái ban đầu giống nhau. Điều này dẫn đến việc các số ngẫu nhiên được sinh ra sau đó sẽ giống nhau giữa các lần chạy chương trình, miễn là bạn sử dụng cùng một giá trị seed.Cùng xử lý nó với
part[3].import hashlib import itertools import random sample = [49, 89, 102, 109, 108, 52] perm = list(itertools.permutations (sample)) for i in perm: random.seed (b'4') temp = list(i) random.shuffle (temp) if (temp == sample): res = list(map(chr, list(i))) print(''.join(res))Phần
part[4]chỉ kiểm tra đơn giản ta đượcpart[4] = '0f'.Lúc này Flag của chúng ta trở thành
amateursCTF{PY7h0ns_ar3_4_f4m1lY_0f_xxxxxxxxxxx_xxxxxx}Gần hoàn thành rồi cùng đến với
part[5]ở đây nhìn có vẻ khoai vì xor random các số từ 0 đến 0xFFFFFFFF nhưng ta đã có seed tại 4. Đây cũng tương tự nhưpart[3]ta sẽ sử dụngseed(4)để hoàn ra được chuỗi cần tìm.import hashlib import itertools import random sample = [49, 89, 102, 109, 108, 52] xor_res = [0xFBFF4501, 825199122, 0xFEEF2AA6] input = [b"", b"", b""] random.seed(b'4') random.shuffle(sample) input[0] = (random.randint(0, 0xFFFFFFFF) ^ xor_res[0]).to_bytes(4, 'little') input[1] = (random.randint(0, 0xFFFFFFFF) ^ xor_res[1]).to_bytes(4, 'little') input[2] = (random.randint(0, 0xFFFFFFFF) ^ xor_res[2]).to_bytes(4, 'little') x = b''.join(input).decode('utf-8') print('part 5 -', x)Sau khi chạy code thì ta được chuỗi
N0Nv3nom0us.Tiếp tục với phần 6 còn lại.
c = 0 for i in input_parts[6]: c *= 128 c += i if hex(c) != '0x29ee69af2f3': return False return TrueTa được chuỗi cuối cùng là
Sn4kessau khi tìmpart[6]bằng đoạn code dưới đây.c = 0x29ee69af2f3 s = [] while c > 0: s.insert(0, c % 128) c //= 128 a = "" for i in s: a += chr(i) print(a)
Result
Vậy ta đã hoàn thành được flag của bài reverse .pyc này
amateursCTF{PY7h0ns_ar3_4_f4m1lY_0f_N0Nv3nom0us_Sn4kes}.
