Curta Cup CTF Writeup

DeFiHackLabs Web3 Security Club Sharing · 24 Nov 2023 · 33:21

Tony KΞ presents a Curta Cup CTF writeup.

Speakers

Topics

From DeFiHackLabs Web3 Security Club Sharing, published by DeFiHackLabs; community: DeFiHackLabs.

Transcript

[Music] okay let's start I was recently asked by a friend where to start when you see a new puzzle and that's a great questions I love solving CDF puzzles because I think the goal of solving a puzzle is very determined and the direction is very clear so I'll start from the requirement first if the puzzle requires the balance of someone to equal to some number I will check the contract to see where I can exploit to make the transfer if I find something I will follow up to check

how can I call this function so on and so forth until I can build up the whole pipeline likewise if I if some states or mapping are required I will check where I can manipulate the states and it could be something simple like solve of message sender equal to two or more complex leverage the upod s store to manipulate the state I prefer to break the whole puzzle into multiple small puzzles and solve it one by one let's let's work through all the puzzles and feel free to interrupt me if you have any questions during the work

through I'll demonstrate the puzzles following the same order as releasing if you haven't play kurur cup yet I suggest you to open the cura WTF website go to the puzzles and put those puzzles on another side of your screen so that make sure you can follow my step when I'm talking about the puzzles I will give you like maybe 20 seconds to prepare okay so the first one is the fundamental

it's pretty short and in this puzzle I need to I need the solve mapping of the message sent to be equal to some value and this value is generated by a function called generate but there is no place to change the so explicitly except in the so function looking into code you can see that if you want to set the Sol you have to meet the requirement that the message send it's a zero adjust which is impossible so I don't know how to make a adjust to to zero adjust so let's just skip it and I notice that the set slot function which allow me to set an arbitr

arbitrator slot with any u in 16 value apparently u in 16 16 is not enough if we want to set the solve because the result of the generate function is a u in 256 so I have to try something else in the so function out of the message sender equal to zero adjust block if the mode of the message sender is in maintenance a serve helper will be called and this serve is a mapping to the helper itself it's a function pointer a function ort in solidity usually means arbitrator jump to a valid jump destination and this is also the

only way you can do an arbitrator jump in solidity as far as I know so the next thing we need to figure out is where we want to jump jump and what parameters should we set for the helper so to analyze the jump des and the parameters you can just dissemble The Bu code but I think that's too hard for hardcore for me so I will Leverage The compilers Help to generate an assemply file that is more human readable it's simple just in your Foundry Tomo file add is actual output files option under the profile sector and review the project you will find an ASM file under the out folder I start from the parameters of

the help function I want to understand the position of the key and key to On The Stack before the jumps so I search the hel per key and key to and goes to the line that is close to the jump instruction and there are too many instructions before this and they look complicated I can analyze the stack by hands but I think it's time consuming and I'm lazy so I just set some random values for these two parameters and start The Foundry debugger to watch the stack boundary debugger is a very good tool if you want to debug execution in upco level and also if useful if you want to watch the stack and the memory a simple command to launch the debugger

it's Forge test debug and your test function name navigating through the up code and I can see that before the jump the stack top is the serve I set and this is what the next Pro program counter will be set following following the St there is the key to and the key okay so we should put this in my memory and going and go on so next we need to figure out what we need to set for the serve message sender our goal is to jump to the sector of the message sender equal to the zero adjust so I found to possible TCH by searching the the statement the Tex here will be

translated into the jump des and offset in the Real by code so the tag 33 is not working because it's going to check the message sender equal to zero adjust we have to try the T 59 to set the solve message sender but is it a good jum Des because I don't see the solve message sender calculated the value of the solve message sender calculated anywhere in Tech 59 because we we need it to be the Genera value so most likely the value is passed from the stack and we need to analyze what kind of Stack value we need so I manual I manually analyze the stack in Tech in

tag 59 and figure out the stack needed for tag 59 the first should be the generated value and the fifs should be a jum desk here we need the jum desk to be somewhere we can stop the execution for the state to be persisted putting together the St analysis of the helper function and the TCH 59 you can see that that the guaranteed value can be mapped to the value of key2 and key2 is also a uint 256 value so this is the correct one we want to use and what about the jump desk to stop I go back to the debug again to check the fifth value of the helper function and luckily it's somehow the

value of the key it's a e in 32 value and it should be enough to contain any J DES in The Bu code so the next step step is to find the John desk to safely exit and we are lucky to find a simple stop Tech and the solution is very clear now you have to set the slot for the MERS apply the slots and then set the slot for serve apply the slot and finally solve with the stop pack and the generative value that's it the fundamental solution and the second one it's kind of hard for me uh and I don't think I fully understand the solution for this puzzles

we get the comp the buy code could be compiled and found it to be like a VM that manipulate the memory in a loop and eventually return a words from the memory my teammate is start enough to figure out the control sequence that can change the output of the execution but we are not able to control the op value after seeing Mina's first BR transaction we get some pins from the adj prefix and able to solve it but I don't think I fully understand it so I think we should ask Mina for the detail write up also to be better understanding of this and Mina is also part of the defy hack laabs Community and doing great in

cdfs so let's just move to the next parles it's the submer and this one is very interesting when I was looking through the code I was starting is staring at how the signature is generated and it doesn't match the general generation of ecds signature so I was trying to search for some way to generate a determined signature for a given priv key but it looks like that is almost impossible and I have to go back to start over we need to have the submerge seed to set to the so set to solve the puzzle in order to set this value we need need the set we need to set the submerged transaction first

approving the trans submerge transactions we need the the trans transaction harsh of the simulator not to be zero searching for the change of the transaction harsh the only PR is in the fallback function of the simulator and and also notice that the hash will be reset at the end of the function so it's impossible to have the transaction hash not to be zero after this function is returned but there is a core inside the fallback function just between setting the transaction hash and reset it and this might be somewhere we can leverage to call the S call the the the submerge

to prove the submerge transactions and another requirement is that the transaction origin balance should be equal to zero here but this is possible if you carefully set the gas price and gas limit to consume all your current balance even if your guas limit is not fully utilized the refund happens after the evm execution so in the evm your balance is zero and we can easily pass this check the transaction hash value comes from the get current transaction hash inside this function we the several parameters were taken from the C data for example see was taken was the first

word of the call data and the signature is derived from the seed the second words of the call data is guas limit and the third is the target to call in the Callback function and the rest of the data is the call data to be used when calling Target a legacy transaction is composed using an on train RP Library and this algorithm is a encoding me of ethereum transactions and other internal data structure so we can use locally we can use the cast tool from Foundry to compose the transaction of chain the order of each FS matter so we need to

follow the same order in the contract code we have to the most important things here is the the gas value and the gas price you need to set set it to consume all your balance and the target it has to be the simulat contract for the input data it has to be set like we said the first one is the seed and the second one is gu limit and third one is the call Target and rest of the data should be the call to the the challenge contract which is also the proof submerge transaction selector because we we want to prove the submerge transaction so once we have the raw transactions

here we can recover the signment using the tool make by abdk if it's a valid signature or a valid valid uh transaction we can say that this is a valid raw transaction so funding the account with exactly gas price multiply by guas limit we can publish the transaction using cost after this the transaction is proved and we can call the proof Sumer C to meet the requirements okay this is the submerge and the next one is the stake friends this puzzle in introduce uh a new protocol the use of The Relic protocol and it's I know I don't know this before

so I do some quick search I know this is a protocol to prove some onch states like account info and logs and Etc we need to have certain amount amount or a large amount of free token to solve the puz so the problem is where to transfer or means a large number of free coin transfer seems impossible because other accounts don't have such a large amount of coins too so we need to Mint and the only way to Mint is call the show friendship to Mint but there is the two passs you can either meet one by making the joint pool a seed or meant

large number amount of uh tokens by making the joint pool revert with specific message Apparently minting one coin multiple times is unrealistic so we have to make the reverse so I search the reverse message and I found it in the beacon deposit contract but it's impossible to have such easer to rever a call basically you have to have more than uh more than anyway a very huge number that is far more than the current supppr of eer so take a look at let's take a look at how the join pools works first of all you need to pass 16 eer value in order

to state but don't worry our goal is to revert and when it revers the free coin contract will refund due the 16 eer following that verify appr is called to validate whether the approver is a trustable approver and found that verify deposit does all the validation except checking whether the lck emitted it's the beacon deposit contract and it also makes a call to the presumed Beacon deposit contract to get the deposit loot that is somewhere we can Leverage The call is to write a contract that emit a fake deposit event with

those required data and also implement the get deposit route to revert with that specific errors after deploying the contract you have to emit the events and get the proof using Relic SDK if you are rich enough you can skip steps three otherwise you have to use the fresh R to acquire 16 eer you can try the fresh wrong service like balancer or D DX they have no fee so we can we are safe to use them and the next one is the user Pur strong the call of this puzzle is to make the call to forge strong function inside the strong

contract adding the user per is calling the add user per is easy because uh it we only need to trigger the D execution and both and it's inside a low Target so it's very easy but for the forge St to be called because the allow method is only the add user per so uh and both allow targets and methods are immutable so we need to do extra trick to make sure we can execute the forage th but so the question is scoping to how we can exploit the D proposal and somehow bypass the allow me restriction we need to take a look at

how the proposal is stored especially the C data the C data is stored inside the CH map with the key the The Proposal ID and the description is stored at the Key of har of two IDs and H that's where we can see the overlap between these two datas the call data location of The Proposal with ID hhx and x overlaps with the description data of Proposal with idx but how can we manipulate the codes of an existing contract we can destruct the contract and recreate the contract on the same address so let's move to how the chip map is implemented to see if the

overwrite is is possible in short it use a proxy contract created by create 2 to create a data contract so the contract code itself could be the data now we know that we have to first we have to first create the proposal with allowed C data which is is the add user and override the Cod data with the this prescription from another proposal so we want it to be the B strong let's take a look at the proxy code and also the data contract so I disembl this uh by code using the evm do codes website this is a

very awesome some website I needed every day and the chip map first create the contract to create to create the new contract from the C data here the C data it's the data you want to store so either the Cod dator of the proposal or the description data and we can see that there is a self self-destruct instruction in the end of the data contract creation which means this proxy contract will be destructed after the data contract is created so now we know that the proxy contract will be destructed once the data contract is created so how can we

destruct the data contract the C data of The Proposal is restricted to only allowed method which is the F thr if we want to destruct the C data contract we have to call it and make it to execute to the self-destruct instruction we can use the cast to calculate the signature of the function easily and luckily it it looks like something valid because the first bite is to push 14 in the instruction table and following that we need 14 bytes 14 random bytes to finish the inst the instruction so after that we we can place a self Dison discon up code to discon the

contract now we have the solution clear we first create a proposal with ID hash and x andx with Cod dat to be push foring and self-destruct next we calculate the adjust of the data contract and call it to destruct it following that we create another Proposal with idx and also set the description data to anything we we want the previous proposal to execute so it's the for R selected and also the parameter and just both both for the proposal and execute it and of course we need to do the same thing for add use suppers too and it's it's more

simple next one it's the adjust gam where you we are required to create a contract and Implement function to return true and the address of the contract need to be fulfilled those requirements on the right hand side of these requirements most like most about the the seed parameters this can be pre calculated so uh I guess that the search space I decide to try for brw force and I guess the search space is small enough for a civil program to search so I write a simple Ras program and quickly get the correct sort to create a suchar contract to meet the

requirements next one is the Lattin risk this one it's funny I reading through the code and and I know that it's a compound stuff and I prefer not to believe that the auor would reveiew a zero zero day exploit in the CDF so it should be some old exploit so I go to the defi hack laabs rapple to search for the compound related keywords and for this so growing the codes together picking the numbers and I am able to solve the solution without knowing what is happening I think there are many analysis to the compound V2 surrounding issues and if you are interested in how

exactly it's working you can try to search and read okay then it's the last one of the H C cup and we took the first Brad of this puzzle in this puzzle we need to get 10,000 of CA Tok basically the kta USD and the kta St USD only the keeper has such large numbers of tokens so my goal scope it to steal tokens from The Keeper moving the focus to the keeper contract there are two possible way to transfer the tokens and the first way it's not working because the withdraw function is restricted by only

owner and the second way might be possible the keeper sets unlimited approvals for the SS manager during the rebalancing at the deployment so I moveed to read the SS manager the depos and withdraw looks fice to me because it doesn't chance large amount of numbers of tokens from the keeper and another place the tokens could be transferred is the Unis swap V2 call this can transfer some amount of CA tokens and the amounts are calculated on the input it looks like this function is restricted by the only unit unit swap V2 pair modifier but this

is super easy to bypass but what can we do if we can use our all pair the code of the pair cannot be changed because I have to deploy the Sam code to make the cohash the same and the only thing I can do to the pair is initializing some previous pre prev States for examples the The Factory address looking into the V2 pair code because I want to know what can I do if I'm the factory adjust I can initialize the pair multiple times and this can help reset the tokens and the reserve numbers

so uh giv that the amount transfer from The Keeper is calculated from the reserve numbers of the pair we we need to carefully calculated the numbers in order to join the keepers the next question is what to set as the token zero and token one for our paay we cannot use the ca tokens because we don't even have the tokens to control the reserve numbers but if we set the tokens to ARS how can we transfer the C tokens from the pair I go back to the pair code again trying to find somewhere I can transfer the tokens and found schem function is a good way to transfer for the tokens if I want to drain the pair the

reserve numbers needs to be zeros and if I want the zero Reserve I should use sync which set the reserve to C barrance of the ccus and that needs me to initialize the pair with some tokens that the pair that doesn't have and the then the solution is clear first we create and initialize the fake pairer with some other tokens Min me calculated amounts of tokens into the pair and sync to adjust the reserve numbers before making this the call to the swap we Min some tokens again into the pair to compensate the swap

fee after the swap call we already have the curent tokens inside the pair because the keeper trying to pay those tokens as the swap fee so so we initialize and sync the pairs again with the new tokens to reset the reserves and now the since the reserve are zeros initialize the pair with the real CTA tokens and call the scheme to get the tokens once you get the tokens you are able to meet the requirement okay that's it and there's no more to share so if you have any questions we are now in Q&A section please feel free to express your

questions yeah very aome uh okay let me ask first one um yeah prity is really spend energy so I I'm curious was it was this all challenges solved by you alone uh actually I think I sove maybe six out of eight okay I see yeah yeah yeah very good yeah yeah I saw many Bia ID on the code yeah if you guys have any question feel free to ask and or if you have any another way to solve the challenge you can also

share with us yes there could be other ways to solve the puzzles and that could be interesting yes yeah I think Mina is not here is not on yeah he's not online okay yeah but Mina will with us to participate uh brait gtf am I pronounced correct yes yeah yeah yeah you can share what why is this event later okay yes any questions

no okay no uh I think we have the hand from Bill H oh hi um so I have a question um do uh this is regarding the user Pur Thorns challenge um so basically um do you know why does the proxy contract uh executes the self-destruct op code even after the return op code so you're asking about why we need

a proxy contract to create the data contract oh no no no it's um oh what I'm asking is why does the proxy contract executes um the self-destruct Ed like after return okay oh so actually let's take a look at the left side this is the proxy contract creation code and on the line of on the program counter of 10 in HEX if the the code is returned which means that the proxy contract is created with the code returned and actually the self-destruct it's not working here

because it's already returned and the execution is stopped and after the creation we have the after the left side of the code is executed we have a contract of the right side and and so so this contract is to create is to basically uh it it it first copi the Cod data from it copy the C data into the memory and use this call dator to call to call the create up code create the data contract and after that just self-destruct it do I answer your question so assuming uh the proy contract is not

self-destructed uh it's it's it's destructed the code of the proxy contract it's on is the real code is the right side so as you can see here on the right side there is a self-destruct at the end of the code and when let's look back into the bottom into the bottom part of the the screen where the solidity solidity function after the create2 the there is a proxy do call with some values and the creation code to call this call is actually calling the the the code on the right side and it's copying some data into the memory

and create the contract and eventually destruct the proxy contract so we now have the proxy contract destructed but we have the data contract created on train okay I I got now thank you cool thank you yeah any question okay so I think no more

question oh okay by the way so uh okay the B the B he is also a strong ctive player maybe you guys already know he got third PR on CA CTF wow that's a yes okay so yeah uh if no more question so if you if anyone is interested in to give a talk letter uh feel to DM me uh we currently have about 10 sessions scheduled in next few months So yeah thank you Tony for sharing

today yeah okay so let's it okay uh Tony yes can you uh introduce about best C CTF when will take place oh for sure so we we Farland we will organize the blaz CF uh at December the 1 this com in the coming week and it's open to all the community and the team size is not limited so welcome to join the events and also pick a team if you don't have any now yeah okay

okay yeah so yeah let's it thank you guys see you next time okay byebye byebye